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 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
== 1) {
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 /* Find out how many lists are needed to be read from pxReadyTasksLists, */
208 int64_t max_used_priority
= 0;
209 retval
= target_read_buffer(rtos
->target
,
210 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
211 param
->pointer_width
,
212 (uint8_t *)&max_used_priority
);
213 if (retval
!= ERROR_OK
)
216 symbol_address_t
*list_of_lists
=
217 (symbol_address_t
*)malloc(sizeof(symbol_address_t
) *
218 (max_used_priority
+1 + 5));
221 for (num_lists
= 0; num_lists
<= max_used_priority
; num_lists
++)
222 list_of_lists
[num_lists
] = rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
+
223 num_lists
* param
->list_width
;
225 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList1
].address
;
226 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList2
].address
;
227 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xPendingReadyList
].address
;
228 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xSuspendedTaskList
].address
;
229 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xTasksWaitingTermination
].address
;
231 for (i
= 0; i
< num_lists
; i
++) {
232 if (list_of_lists
[i
] == 0)
235 /* Read the number of threads in this list */
236 int64_t list_thread_count
= 0;
237 retval
= target_read_buffer(rtos
->target
,
239 param
->thread_count_width
,
240 (uint8_t *)&list_thread_count
);
241 if (retval
!= ERROR_OK
) {
242 LOG_OUTPUT("Error reading number of threads in FreeRTOS thread list\r\n");
246 if (list_thread_count
== 0)
249 /* Read the location of first list item */
250 uint64_t prev_list_elem_ptr
= -1;
251 uint64_t list_elem_ptr
= 0;
252 retval
= target_read_buffer(rtos
->target
,
253 list_of_lists
[i
] + param
->list_next_offset
,
254 param
->pointer_width
,
255 (uint8_t *)&list_elem_ptr
);
256 if (retval
!= ERROR_OK
) {
258 "Error reading first thread item location in FreeRTOS thread list\r\n");
262 while ((list_thread_count
> 0) && (list_elem_ptr
!= 0) &&
263 (list_elem_ptr
!= prev_list_elem_ptr
) &&
264 (tasks_found
< thread_list_size
)) {
265 /* Get the location of the thread structure. */
266 rtos
->thread_details
[tasks_found
].threadid
= 0;
267 retval
= target_read_buffer(rtos
->target
,
268 list_elem_ptr
+ param
->list_elem_content_offset
,
269 param
->pointer_width
,
270 (uint8_t *)&(rtos
->thread_details
[tasks_found
].threadid
));
271 if (retval
!= ERROR_OK
) {
273 "Error reading thread list item object in FreeRTOS thread list\r\n");
277 /* get thread name */
279 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
280 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
282 /* Read the thread name */
283 retval
= target_read_buffer(rtos
->target
,
284 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
285 FREERTOS_THREAD_NAME_STR_SIZE
,
286 (uint8_t *)&tmp_str
);
287 if (retval
!= ERROR_OK
) {
289 "Error reading first thread item location in FreeRTOS thread list\r\n");
292 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
294 if (tmp_str
[0] == '\x00')
295 strcpy(tmp_str
, "No Name");
297 rtos
->thread_details
[tasks_found
].thread_name_str
=
298 (char *)malloc(strlen(tmp_str
)+1);
299 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
300 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
301 rtos
->thread_details
[tasks_found
].exists
= true;
303 if (rtos
->thread_details
[tasks_found
].threadid
== rtos
->current_thread
) {
304 char running_str
[] = "Running";
305 rtos
->thread_details
[tasks_found
].extra_info_str
= (char *) malloc(
306 sizeof(running_str
));
307 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
,
310 rtos
->thread_details
[tasks_found
].extra_info_str
= NULL
;
315 prev_list_elem_ptr
= list_elem_ptr
;
317 retval
= target_read_buffer(rtos
->target
,
318 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
319 param
->pointer_width
,
320 (uint8_t *)&list_elem_ptr
);
321 if (retval
!= ERROR_OK
) {
323 "Error reading next thread item location in FreeRTOS thread list\r\n");
329 rtos
->thread_count
= tasks_found
;
333 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
336 const struct FreeRTOS_params
*param
;
337 int64_t stack_ptr
= 0;
339 *hex_reg_list
= NULL
;
346 if (rtos
->rtos_specific_params
== NULL
)
349 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
351 /* Read the stack pointer */
352 retval
= target_read_buffer(rtos
->target
,
353 thread_id
+ param
->thread_stack_offset
,
354 param
->pointer_width
,
355 (uint8_t *)&stack_ptr
);
356 if (retval
!= ERROR_OK
) {
357 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
361 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
365 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
368 *symbol_list
= (symbol_table_elem_t
*) malloc(
369 sizeof(symbol_table_elem_t
) * FREERTOS_NUM_SYMBOLS
);
371 for (i
= 0; i
< FREERTOS_NUM_SYMBOLS
; i
++)
372 (*symbol_list
)[i
].symbol_name
= FreeRTOS_symbol_list
[i
];
379 static int FreeRTOS_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
384 static int FreeRTOS_get_thread_ascii_info(struct rtos
*rtos
, threadid_t thread_id
, char **info
)
387 const struct FreeRTOS_params
*param
;
395 if (rtos
->rtos_specific_params
== NULL
)
398 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
400 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
401 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
403 /* Read the thread name */
404 retval
= target_read_buffer(rtos
->target
,
405 thread_id
+ param
->thread_name_offset
,
406 FREERTOS_THREAD_NAME_STR_SIZE
,
407 (uint8_t *)&tmp_str
);
408 if (retval
!= ERROR_OK
) {
409 LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
412 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
414 if (tmp_str
[0] == '\x00')
415 strcpy(tmp_str
, "No Name");
417 *info
= (char *)malloc(strlen(tmp_str
)+1);
418 strcpy(*info
, tmp_str
);
424 static int FreeRTOS_detect_rtos(struct target
*target
)
426 if ((target
->rtos
->symbols
!= NULL
) &&
427 (target
->rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
!= 0)) {
428 /* looks like FreeRTOS */
434 static int FreeRTOS_create(struct target
*target
)
437 while ((i
< FREERTOS_NUM_PARAMS
) &&
438 (0 != strcmp(FreeRTOS_params_list
[i
].target_name
, target
->type
->name
))) {
441 if (i
>= FREERTOS_NUM_PARAMS
) {
442 LOG_OUTPUT("Could not find target in FreeRTOS compatibility list\r\n");
446 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)