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 */
64 "stm32_stlink", /* target_name */
65 4, /* thread_count_width; */
66 4, /* pointer_width; */
67 16, /* list_next_offset; */
69 8, /* list_elem_next_offset; */
70 12, /* list_elem_content_offset */
71 0, /* thread_stack_offset; */
72 52, /* thread_name_offset; */
73 &rtos_standard_Cortex_M3_stacking
, /* stacking_info */
77 #define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
79 static int FreeRTOS_detect_rtos(struct target
*target
);
80 static int FreeRTOS_create(struct target
*target
);
81 static int FreeRTOS_update_threads(struct rtos
*rtos
);
82 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
);
83 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
85 struct rtos_type FreeRTOS_rtos
= {
88 .detect_rtos
= FreeRTOS_detect_rtos
,
89 .create
= FreeRTOS_create
,
90 .update_threads
= FreeRTOS_update_threads
,
91 .get_thread_reg_list
= FreeRTOS_get_thread_reg_list
,
92 .get_symbol_list_to_lookup
= FreeRTOS_get_symbol_list_to_lookup
,
95 enum FreeRTOS_symbol_values
{
96 FreeRTOS_VAL_pxCurrentTCB
= 0,
97 FreeRTOS_VAL_pxReadyTasksLists
= 1,
98 FreeRTOS_VAL_xDelayedTaskList1
= 2,
99 FreeRTOS_VAL_xDelayedTaskList2
= 3,
100 FreeRTOS_VAL_pxDelayedTaskList
= 4,
101 FreeRTOS_VAL_pxOverflowDelayedTaskList
= 5,
102 FreeRTOS_VAL_xPendingReadyList
= 6,
103 FreeRTOS_VAL_xTasksWaitingTermination
= 7,
104 FreeRTOS_VAL_xSuspendedTaskList
= 8,
105 FreeRTOS_VAL_uxCurrentNumberOfTasks
= 9,
106 FreeRTOS_VAL_uxTopUsedPriority
= 10,
109 static char *FreeRTOS_symbol_list
[] = {
115 "pxOverflowDelayedTaskList",
117 "xTasksWaitingTermination",
118 "xSuspendedTaskList",
119 "uxCurrentNumberOfTasks",
124 #define FREERTOS_NUM_SYMBOLS (sizeof(FreeRTOS_symbol_list)/sizeof(char *))
127 /* this is not safe for little endian yet */
128 /* may be problems reading if sizes are not 32 bit long integers. */
129 /* test mallocs for failure */
131 static int FreeRTOS_update_threads(struct rtos
*rtos
)
136 const struct FreeRTOS_params
*param
;
138 if (rtos
->rtos_specific_params
== NULL
)
141 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
143 if (rtos
->symbols
== NULL
) {
144 LOG_OUTPUT("No symbols for FreeRTOS\r\n");
148 if (rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
== 0) {
149 LOG_OUTPUT("Don't have the number of threads in FreeRTOS \r\n");
153 int thread_list_size
= 0;
154 retval
= target_read_buffer(rtos
->target
,
155 rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
,
156 param
->thread_count_width
,
157 (uint8_t *)&thread_list_size
);
159 if (retval
!= ERROR_OK
) {
160 LOG_OUTPUT("Could not read FreeRTOS thread count from target\r\n");
164 /* wipe out previous thread details if any */
165 if (rtos
->thread_details
!= NULL
) {
167 for (j
= 0; j
< rtos
->thread_count
; j
++) {
168 if (rtos
->thread_details
[j
].display_str
!= NULL
) {
169 free(rtos
->thread_details
[j
].display_str
);
170 rtos
->thread_details
[j
].display_str
= NULL
;
172 if (rtos
->thread_details
[j
].thread_name_str
!= NULL
) {
173 free(rtos
->thread_details
[j
].thread_name_str
);
174 rtos
->thread_details
[j
].thread_name_str
= NULL
;
176 if (rtos
->thread_details
[j
].extra_info_str
!= NULL
) {
177 free(rtos
->thread_details
[j
].extra_info_str
);
178 rtos
->thread_details
[j
].extra_info_str
= NULL
;
181 free(rtos
->thread_details
);
182 rtos
->thread_details
= NULL
;
185 /* read the current thread */
186 retval
= target_read_buffer(rtos
->target
,
187 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
188 param
->pointer_width
,
189 (uint8_t *)&rtos
->current_thread
);
190 if (retval
!= ERROR_OK
) {
191 LOG_OUTPUT("Error reading current thread in FreeRTOS thread list\r\n");
195 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
196 /* Either : No RTOS threads - there is always at least the current execution though */
197 /* OR : No current thread - all threads suspended - show the current execution
199 char tmp_str
[] = "Current Execution";
202 rtos
->thread_details
= (struct thread_detail
*) malloc(
203 sizeof(struct thread_detail
) * thread_list_size
);
204 if (!rtos
->thread_details
) {
205 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
208 rtos
->thread_details
->threadid
= 1;
209 rtos
->thread_details
->exists
= true;
210 rtos
->thread_details
->display_str
= NULL
;
211 rtos
->thread_details
->extra_info_str
= NULL
;
212 rtos
->thread_details
->thread_name_str
= (char *) malloc(sizeof(tmp_str
));
213 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
215 if (thread_list_size
== 1) {
216 rtos
->thread_count
= 1;
220 /* create space for new thread details */
221 rtos
->thread_details
= (struct thread_detail
*) malloc(
222 sizeof(struct thread_detail
) * thread_list_size
);
223 if (!rtos
->thread_details
) {
224 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
229 /* Find out how many lists are needed to be read from pxReadyTasksLists, */
230 int64_t max_used_priority
= 0;
231 retval
= target_read_buffer(rtos
->target
,
232 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
233 param
->pointer_width
,
234 (uint8_t *)&max_used_priority
);
235 if (retval
!= ERROR_OK
)
237 if (max_used_priority
> FREERTOS_MAX_PRIORITIES
) {
238 LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64
"",
243 symbol_address_t
*list_of_lists
=
244 (symbol_address_t
*)malloc(sizeof(symbol_address_t
) *
245 (max_used_priority
+1 + 5));
246 if (!list_of_lists
) {
247 LOG_ERROR("Error allocating memory for %" PRId64
" priorities", max_used_priority
);
252 for (num_lists
= 0; num_lists
<= max_used_priority
; num_lists
++)
253 list_of_lists
[num_lists
] = rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
+
254 num_lists
* param
->list_width
;
256 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList1
].address
;
257 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList2
].address
;
258 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xPendingReadyList
].address
;
259 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xSuspendedTaskList
].address
;
260 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xTasksWaitingTermination
].address
;
262 for (i
= 0; i
< num_lists
; i
++) {
263 if (list_of_lists
[i
] == 0)
266 /* Read the number of threads in this list */
267 int64_t list_thread_count
= 0;
268 retval
= target_read_buffer(rtos
->target
,
270 param
->thread_count_width
,
271 (uint8_t *)&list_thread_count
);
272 if (retval
!= ERROR_OK
) {
273 LOG_OUTPUT("Error reading number of threads in FreeRTOS thread list\r\n");
278 if (list_thread_count
== 0)
281 /* Read the location of first list item */
282 uint64_t prev_list_elem_ptr
= -1;
283 uint64_t list_elem_ptr
= 0;
284 retval
= target_read_buffer(rtos
->target
,
285 list_of_lists
[i
] + param
->list_next_offset
,
286 param
->pointer_width
,
287 (uint8_t *)&list_elem_ptr
);
288 if (retval
!= ERROR_OK
) {
289 LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
294 while ((list_thread_count
> 0) && (list_elem_ptr
!= 0) &&
295 (list_elem_ptr
!= prev_list_elem_ptr
) &&
296 (tasks_found
< thread_list_size
)) {
297 /* Get the location of the thread structure. */
298 rtos
->thread_details
[tasks_found
].threadid
= 0;
299 retval
= target_read_buffer(rtos
->target
,
300 list_elem_ptr
+ param
->list_elem_content_offset
,
301 param
->pointer_width
,
302 (uint8_t *)&(rtos
->thread_details
[tasks_found
].threadid
));
303 if (retval
!= ERROR_OK
) {
304 LOG_OUTPUT("Error reading thread list item object in FreeRTOS thread list\r\n");
309 /* get thread name */
311 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
312 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
314 /* Read the thread name */
315 retval
= target_read_buffer(rtos
->target
,
316 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
317 FREERTOS_THREAD_NAME_STR_SIZE
,
318 (uint8_t *)&tmp_str
);
319 if (retval
!= ERROR_OK
) {
320 LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
324 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
326 if (tmp_str
[0] == '\x00')
327 strcpy(tmp_str
, "No Name");
329 rtos
->thread_details
[tasks_found
].thread_name_str
=
330 (char *)malloc(strlen(tmp_str
)+1);
331 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
332 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
333 rtos
->thread_details
[tasks_found
].exists
= true;
335 if (rtos
->thread_details
[tasks_found
].threadid
== rtos
->current_thread
) {
336 char running_str
[] = "Running";
337 rtos
->thread_details
[tasks_found
].extra_info_str
= (char *) malloc(
338 sizeof(running_str
));
339 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
,
342 rtos
->thread_details
[tasks_found
].extra_info_str
= NULL
;
347 prev_list_elem_ptr
= list_elem_ptr
;
349 retval
= target_read_buffer(rtos
->target
,
350 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
351 param
->pointer_width
,
352 (uint8_t *)&list_elem_ptr
);
353 if (retval
!= ERROR_OK
) {
354 LOG_OUTPUT("Error reading next thread item location in FreeRTOS thread list\r\n");
362 rtos
->thread_count
= tasks_found
;
366 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
369 const struct FreeRTOS_params
*param
;
370 int64_t stack_ptr
= 0;
372 *hex_reg_list
= NULL
;
379 if (rtos
->rtos_specific_params
== NULL
)
382 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
384 /* Read the stack pointer */
385 retval
= target_read_buffer(rtos
->target
,
386 thread_id
+ param
->thread_stack_offset
,
387 param
->pointer_width
,
388 (uint8_t *)&stack_ptr
);
389 if (retval
!= ERROR_OK
) {
390 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
394 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
398 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
401 *symbol_list
= (symbol_table_elem_t
*) malloc(
402 sizeof(symbol_table_elem_t
) * FREERTOS_NUM_SYMBOLS
);
404 for (i
= 0; i
< FREERTOS_NUM_SYMBOLS
; i
++)
405 (*symbol_list
)[i
].symbol_name
= FreeRTOS_symbol_list
[i
];
412 static int FreeRTOS_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
417 static int FreeRTOS_get_thread_ascii_info(struct rtos
*rtos
, threadid_t thread_id
, char **info
)
420 const struct FreeRTOS_params
*param
;
428 if (rtos
->rtos_specific_params
== NULL
)
431 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
433 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
434 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
436 /* Read the thread name */
437 retval
= target_read_buffer(rtos
->target
,
438 thread_id
+ param
->thread_name_offset
,
439 FREERTOS_THREAD_NAME_STR_SIZE
,
440 (uint8_t *)&tmp_str
);
441 if (retval
!= ERROR_OK
) {
442 LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
445 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
447 if (tmp_str
[0] == '\x00')
448 strcpy(tmp_str
, "No Name");
450 *info
= (char *)malloc(strlen(tmp_str
)+1);
451 strcpy(*info
, tmp_str
);
457 static int FreeRTOS_detect_rtos(struct target
*target
)
459 if ((target
->rtos
->symbols
!= NULL
) &&
460 (target
->rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
!= 0)) {
461 /* looks like FreeRTOS */
467 static int FreeRTOS_create(struct target
*target
)
470 while ((i
< FREERTOS_NUM_PARAMS
) &&
471 (0 != strcmp(FreeRTOS_params_list
[i
].target_name
, target
->type
->name
))) {
474 if (i
>= FREERTOS_NUM_PARAMS
) {
475 LOG_OUTPUT("Could not find target in FreeRTOS compatibility list\r\n");
479 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)