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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 static const struct FreeRTOS_params FreeRTOS_params_list
[] = {
53 "cortex_m", /* 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 */
77 "nds32_v3", /* target_name */
78 4, /* thread_count_width; */
79 4, /* pointer_width; */
80 16, /* list_next_offset; */
82 8, /* list_elem_next_offset; */
83 12, /* list_elem_content_offset */
84 0, /* thread_stack_offset; */
85 52, /* thread_name_offset; */
86 &rtos_standard_NDS32_N1068_stacking
, /* stacking_info */
90 #define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
92 static int FreeRTOS_detect_rtos(struct target
*target
);
93 static int FreeRTOS_create(struct target
*target
);
94 static int FreeRTOS_update_threads(struct rtos
*rtos
);
95 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
);
96 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
98 struct rtos_type FreeRTOS_rtos
= {
101 .detect_rtos
= FreeRTOS_detect_rtos
,
102 .create
= FreeRTOS_create
,
103 .update_threads
= FreeRTOS_update_threads
,
104 .get_thread_reg_list
= FreeRTOS_get_thread_reg_list
,
105 .get_symbol_list_to_lookup
= FreeRTOS_get_symbol_list_to_lookup
,
108 enum FreeRTOS_symbol_values
{
109 FreeRTOS_VAL_pxCurrentTCB
= 0,
110 FreeRTOS_VAL_pxReadyTasksLists
= 1,
111 FreeRTOS_VAL_xDelayedTaskList1
= 2,
112 FreeRTOS_VAL_xDelayedTaskList2
= 3,
113 FreeRTOS_VAL_pxDelayedTaskList
= 4,
114 FreeRTOS_VAL_pxOverflowDelayedTaskList
= 5,
115 FreeRTOS_VAL_xPendingReadyList
= 6,
116 FreeRTOS_VAL_xTasksWaitingTermination
= 7,
117 FreeRTOS_VAL_xSuspendedTaskList
= 8,
118 FreeRTOS_VAL_uxCurrentNumberOfTasks
= 9,
119 FreeRTOS_VAL_uxTopUsedPriority
= 10,
122 static const char * const FreeRTOS_symbol_list
[] = {
128 "pxOverflowDelayedTaskList",
130 "xTasksWaitingTermination",
131 "xSuspendedTaskList",
132 "uxCurrentNumberOfTasks",
138 /* this is not safe for little endian yet */
139 /* may be problems reading if sizes are not 32 bit long integers. */
140 /* test mallocs for failure */
142 static int FreeRTOS_update_threads(struct rtos
*rtos
)
147 const struct FreeRTOS_params
*param
;
149 if (rtos
->rtos_specific_params
== NULL
)
152 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
154 if (rtos
->symbols
== NULL
) {
155 LOG_ERROR("No symbols for FreeRTOS");
159 if (rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
== 0) {
160 LOG_ERROR("Don't have the number of threads in FreeRTOS");
164 int thread_list_size
= 0;
165 retval
= target_read_buffer(rtos
->target
,
166 rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
,
167 param
->thread_count_width
,
168 (uint8_t *)&thread_list_size
);
169 LOG_DEBUG("FreeRTOS: Read uxCurrentNumberOfTasks at 0x%" PRIx64
", value %d\r\n",
170 rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
,
173 if (retval
!= ERROR_OK
) {
174 LOG_ERROR("Could not read FreeRTOS thread count from target");
178 /* wipe out previous thread details if any */
179 rtos_free_threadlist(rtos
);
181 /* read the current thread */
182 retval
= target_read_buffer(rtos
->target
,
183 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
184 param
->pointer_width
,
185 (uint8_t *)&rtos
->current_thread
);
186 if (retval
!= ERROR_OK
) {
187 LOG_ERROR("Error reading current thread in FreeRTOS thread list");
190 LOG_DEBUG("FreeRTOS: Read pxCurrentTCB at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
191 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
192 rtos
->current_thread
);
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
= 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
= 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
= 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 LOG_DEBUG("FreeRTOS: Read uxTopUsedPriority at 0x%" PRIx64
", value %" PRId64
"\r\n",
237 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
239 if (max_used_priority
> FREERTOS_MAX_PRIORITIES
) {
240 LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64
"",
245 symbol_address_t
*list_of_lists
=
246 malloc(sizeof(symbol_address_t
) *
247 (max_used_priority
+1 + 5));
248 if (!list_of_lists
) {
249 LOG_ERROR("Error allocating memory for %" PRId64
" priorities", max_used_priority
);
254 for (num_lists
= 0; num_lists
<= max_used_priority
; num_lists
++)
255 list_of_lists
[num_lists
] = rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
+
256 num_lists
* param
->list_width
;
258 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList1
].address
;
259 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList2
].address
;
260 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xPendingReadyList
].address
;
261 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xSuspendedTaskList
].address
;
262 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xTasksWaitingTermination
].address
;
264 for (i
= 0; i
< num_lists
; i
++) {
265 if (list_of_lists
[i
] == 0)
268 /* Read the number of threads in this list */
269 int64_t list_thread_count
= 0;
270 retval
= target_read_buffer(rtos
->target
,
272 param
->thread_count_width
,
273 (uint8_t *)&list_thread_count
);
274 if (retval
!= ERROR_OK
) {
275 LOG_ERROR("Error reading number of threads in FreeRTOS thread list");
279 LOG_DEBUG("FreeRTOS: Read thread count for list %d at 0x%" PRIx64
", value %" PRId64
"\r\n",
280 i
, list_of_lists
[i
], list_thread_count
);
282 if (list_thread_count
== 0)
285 /* Read the location of first list item */
286 uint64_t prev_list_elem_ptr
= -1;
287 uint64_t list_elem_ptr
= 0;
288 retval
= target_read_buffer(rtos
->target
,
289 list_of_lists
[i
] + param
->list_next_offset
,
290 param
->pointer_width
,
291 (uint8_t *)&list_elem_ptr
);
292 if (retval
!= ERROR_OK
) {
293 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
297 LOG_DEBUG("FreeRTOS: Read first item for list %d at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
298 i
, list_of_lists
[i
] + param
->list_next_offset
, list_elem_ptr
);
300 while ((list_thread_count
> 0) && (list_elem_ptr
!= 0) &&
301 (list_elem_ptr
!= prev_list_elem_ptr
) &&
302 (tasks_found
< thread_list_size
)) {
303 /* Get the location of the thread structure. */
304 rtos
->thread_details
[tasks_found
].threadid
= 0;
305 retval
= target_read_buffer(rtos
->target
,
306 list_elem_ptr
+ param
->list_elem_content_offset
,
307 param
->pointer_width
,
308 (uint8_t *)&(rtos
->thread_details
[tasks_found
].threadid
));
309 if (retval
!= ERROR_OK
) {
310 LOG_ERROR("Error reading thread list item object in FreeRTOS thread list");
314 LOG_DEBUG("FreeRTOS: Read Thread ID at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
315 list_elem_ptr
+ param
->list_elem_content_offset
,
316 rtos
->thread_details
[tasks_found
].threadid
);
318 /* get thread name */
320 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
321 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
323 /* Read the thread name */
324 retval
= target_read_buffer(rtos
->target
,
325 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
326 FREERTOS_THREAD_NAME_STR_SIZE
,
327 (uint8_t *)&tmp_str
);
328 if (retval
!= ERROR_OK
) {
329 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
333 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
334 LOG_DEBUG("FreeRTOS: Read Thread Name at 0x%" PRIx64
", value \"%s\"\r\n",
335 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
338 if (tmp_str
[0] == '\x00')
339 strcpy(tmp_str
, "No Name");
341 rtos
->thread_details
[tasks_found
].thread_name_str
=
342 malloc(strlen(tmp_str
)+1);
343 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
344 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
345 rtos
->thread_details
[tasks_found
].exists
= true;
347 if (rtos
->thread_details
[tasks_found
].threadid
== rtos
->current_thread
) {
348 char running_str
[] = "Running";
349 rtos
->thread_details
[tasks_found
].extra_info_str
= malloc(
350 sizeof(running_str
));
351 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
,
354 rtos
->thread_details
[tasks_found
].extra_info_str
= NULL
;
359 prev_list_elem_ptr
= list_elem_ptr
;
361 retval
= target_read_buffer(rtos
->target
,
362 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
363 param
->pointer_width
,
364 (uint8_t *)&list_elem_ptr
);
365 if (retval
!= ERROR_OK
) {
366 LOG_ERROR("Error reading next thread item location in FreeRTOS thread list");
370 LOG_DEBUG("FreeRTOS: Read next thread location at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
371 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
377 rtos
->thread_count
= tasks_found
;
381 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
384 const struct FreeRTOS_params
*param
;
385 int64_t stack_ptr
= 0;
387 *hex_reg_list
= NULL
;
394 if (rtos
->rtos_specific_params
== NULL
)
397 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
399 /* Read the stack pointer */
400 retval
= target_read_buffer(rtos
->target
,
401 thread_id
+ param
->thread_stack_offset
,
402 param
->pointer_width
,
403 (uint8_t *)&stack_ptr
);
404 if (retval
!= ERROR_OK
) {
405 LOG_ERROR("Error reading stack frame from FreeRTOS thread");
408 LOG_DEBUG("FreeRTOS: Read stack pointer at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
409 thread_id
+ param
->thread_stack_offset
,
412 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
415 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
418 *symbol_list
= calloc(
419 ARRAY_SIZE(FreeRTOS_symbol_list
), sizeof(symbol_table_elem_t
));
421 for (i
= 0; i
< ARRAY_SIZE(FreeRTOS_symbol_list
); i
++)
422 (*symbol_list
)[i
].symbol_name
= FreeRTOS_symbol_list
[i
];
429 static int FreeRTOS_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
434 static int FreeRTOS_get_thread_ascii_info(struct rtos
*rtos
, threadid_t thread_id
, char **info
)
437 const struct FreeRTOS_params
*param
;
445 if (rtos
->rtos_specific_params
== NULL
)
448 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
450 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
451 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
453 /* Read the thread name */
454 retval
= target_read_buffer(rtos
->target
,
455 thread_id
+ param
->thread_name_offset
,
456 FREERTOS_THREAD_NAME_STR_SIZE
,
457 (uint8_t *)&tmp_str
);
458 if (retval
!= ERROR_OK
) {
459 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
462 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
464 if (tmp_str
[0] == '\x00')
465 strcpy(tmp_str
, "No Name");
467 *info
= malloc(strlen(tmp_str
)+1);
468 strcpy(*info
, tmp_str
);
474 static int FreeRTOS_detect_rtos(struct target
*target
)
476 if ((target
->rtos
->symbols
!= NULL
) &&
477 (target
->rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
!= 0)) {
478 /* looks like FreeRTOS */
484 static int FreeRTOS_create(struct target
*target
)
487 while ((i
< FREERTOS_NUM_PARAMS
) &&
488 (0 != strcmp(FreeRTOS_params_list
[i
].target_name
, target
->type
->name
))) {
491 if (i
>= FREERTOS_NUM_PARAMS
) {
492 LOG_ERROR("Could not find target in FreeRTOS compatibility list");
496 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)