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,
127 static const struct symbols FreeRTOS_symbol_list
[] = {
128 { "pxCurrentTCB", false },
129 { "pxReadyTasksLists", false },
130 { "xDelayedTaskList1", false },
131 { "xDelayedTaskList2", false },
132 { "pxDelayedTaskList", false },
133 { "pxOverflowDelayedTaskList", false },
134 { "xPendingReadyList", false },
135 { "xTasksWaitingTermination", true }, /* Only if INCLUDE_vTaskDelete */
136 { "xSuspendedTaskList", true }, /* Only if INCLUDE_vTaskSuspend */
137 { "uxCurrentNumberOfTasks", false },
138 { "uxTopUsedPriority", false },
143 /* this is not safe for little endian yet */
144 /* may be problems reading if sizes are not 32 bit long integers. */
145 /* test mallocs for failure */
147 static int FreeRTOS_update_threads(struct rtos
*rtos
)
152 const struct FreeRTOS_params
*param
;
154 if (rtos
->rtos_specific_params
== NULL
)
157 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
159 if (rtos
->symbols
== NULL
) {
160 LOG_ERROR("No symbols for FreeRTOS");
164 if (rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
== 0) {
165 LOG_ERROR("Don't have the number of threads in FreeRTOS");
169 int thread_list_size
= 0;
170 retval
= target_read_buffer(rtos
->target
,
171 rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
,
172 param
->thread_count_width
,
173 (uint8_t *)&thread_list_size
);
174 LOG_DEBUG("FreeRTOS: Read uxCurrentNumberOfTasks at 0x%" PRIx64
", value %d\r\n",
175 rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
,
178 if (retval
!= ERROR_OK
) {
179 LOG_ERROR("Could not read FreeRTOS thread count from target");
183 /* wipe out previous thread details if any */
184 rtos_free_threadlist(rtos
);
186 /* read the current thread */
187 retval
= target_read_buffer(rtos
->target
,
188 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
189 param
->pointer_width
,
190 (uint8_t *)&rtos
->current_thread
);
191 if (retval
!= ERROR_OK
) {
192 LOG_ERROR("Error reading current thread in FreeRTOS thread list");
195 LOG_DEBUG("FreeRTOS: Read pxCurrentTCB at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
196 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
197 rtos
->current_thread
);
199 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
200 /* Either : No RTOS threads - there is always at least the current execution though */
201 /* OR : No current thread - all threads suspended - show the current execution
203 char tmp_str
[] = "Current Execution";
206 rtos
->thread_details
= malloc(
207 sizeof(struct thread_detail
) * thread_list_size
);
208 if (!rtos
->thread_details
) {
209 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
212 rtos
->thread_details
->threadid
= 1;
213 rtos
->thread_details
->exists
= true;
214 rtos
->thread_details
->display_str
= NULL
;
215 rtos
->thread_details
->extra_info_str
= NULL
;
216 rtos
->thread_details
->thread_name_str
= malloc(sizeof(tmp_str
));
217 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
219 if (thread_list_size
== 1) {
220 rtos
->thread_count
= 1;
224 /* create space for new thread details */
225 rtos
->thread_details
= malloc(
226 sizeof(struct thread_detail
) * thread_list_size
);
227 if (!rtos
->thread_details
) {
228 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
233 /* Find out how many lists are needed to be read from pxReadyTasksLists, */
234 int64_t max_used_priority
= 0;
235 retval
= target_read_buffer(rtos
->target
,
236 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
237 param
->pointer_width
,
238 (uint8_t *)&max_used_priority
);
239 if (retval
!= ERROR_OK
)
241 LOG_DEBUG("FreeRTOS: Read uxTopUsedPriority at 0x%" PRIx64
", value %" PRId64
"\r\n",
242 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
244 if (max_used_priority
> FREERTOS_MAX_PRIORITIES
) {
245 LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64
"",
250 symbol_address_t
*list_of_lists
=
251 malloc(sizeof(symbol_address_t
) *
252 (max_used_priority
+1 + 5));
253 if (!list_of_lists
) {
254 LOG_ERROR("Error allocating memory for %" PRId64
" priorities", max_used_priority
);
259 for (num_lists
= 0; num_lists
<= max_used_priority
; num_lists
++)
260 list_of_lists
[num_lists
] = rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
+
261 num_lists
* param
->list_width
;
263 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList1
].address
;
264 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList2
].address
;
265 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xPendingReadyList
].address
;
266 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xSuspendedTaskList
].address
;
267 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xTasksWaitingTermination
].address
;
269 for (i
= 0; i
< num_lists
; i
++) {
270 if (list_of_lists
[i
] == 0)
273 /* Read the number of threads in this list */
274 int64_t list_thread_count
= 0;
275 retval
= target_read_buffer(rtos
->target
,
277 param
->thread_count_width
,
278 (uint8_t *)&list_thread_count
);
279 if (retval
!= ERROR_OK
) {
280 LOG_ERROR("Error reading number of threads in FreeRTOS thread list");
284 LOG_DEBUG("FreeRTOS: Read thread count for list %d at 0x%" PRIx64
", value %" PRId64
"\r\n",
285 i
, list_of_lists
[i
], list_thread_count
);
287 if (list_thread_count
== 0)
290 /* Read the location of first list item */
291 uint64_t prev_list_elem_ptr
= -1;
292 uint64_t list_elem_ptr
= 0;
293 retval
= target_read_buffer(rtos
->target
,
294 list_of_lists
[i
] + param
->list_next_offset
,
295 param
->pointer_width
,
296 (uint8_t *)&list_elem_ptr
);
297 if (retval
!= ERROR_OK
) {
298 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
302 LOG_DEBUG("FreeRTOS: Read first item for list %d at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
303 i
, list_of_lists
[i
] + param
->list_next_offset
, list_elem_ptr
);
305 while ((list_thread_count
> 0) && (list_elem_ptr
!= 0) &&
306 (list_elem_ptr
!= prev_list_elem_ptr
) &&
307 (tasks_found
< thread_list_size
)) {
308 /* Get the location of the thread structure. */
309 rtos
->thread_details
[tasks_found
].threadid
= 0;
310 retval
= target_read_buffer(rtos
->target
,
311 list_elem_ptr
+ param
->list_elem_content_offset
,
312 param
->pointer_width
,
313 (uint8_t *)&(rtos
->thread_details
[tasks_found
].threadid
));
314 if (retval
!= ERROR_OK
) {
315 LOG_ERROR("Error reading thread list item object in FreeRTOS thread list");
319 LOG_DEBUG("FreeRTOS: Read Thread ID at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
320 list_elem_ptr
+ param
->list_elem_content_offset
,
321 rtos
->thread_details
[tasks_found
].threadid
);
323 /* get thread name */
325 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
326 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
328 /* Read the thread name */
329 retval
= target_read_buffer(rtos
->target
,
330 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
331 FREERTOS_THREAD_NAME_STR_SIZE
,
332 (uint8_t *)&tmp_str
);
333 if (retval
!= ERROR_OK
) {
334 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
338 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
339 LOG_DEBUG("FreeRTOS: Read Thread Name at 0x%" PRIx64
", value \"%s\"\r\n",
340 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
343 if (tmp_str
[0] == '\x00')
344 strcpy(tmp_str
, "No Name");
346 rtos
->thread_details
[tasks_found
].thread_name_str
=
347 malloc(strlen(tmp_str
)+1);
348 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
349 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
350 rtos
->thread_details
[tasks_found
].exists
= true;
352 if (rtos
->thread_details
[tasks_found
].threadid
== rtos
->current_thread
) {
353 char running_str
[] = "Running";
354 rtos
->thread_details
[tasks_found
].extra_info_str
= malloc(
355 sizeof(running_str
));
356 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
,
359 rtos
->thread_details
[tasks_found
].extra_info_str
= NULL
;
364 prev_list_elem_ptr
= list_elem_ptr
;
366 retval
= target_read_buffer(rtos
->target
,
367 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
368 param
->pointer_width
,
369 (uint8_t *)&list_elem_ptr
);
370 if (retval
!= ERROR_OK
) {
371 LOG_ERROR("Error reading next thread item location in FreeRTOS thread list");
375 LOG_DEBUG("FreeRTOS: Read next thread location at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
376 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
382 rtos
->thread_count
= tasks_found
;
386 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
389 const struct FreeRTOS_params
*param
;
390 int64_t stack_ptr
= 0;
392 *hex_reg_list
= NULL
;
399 if (rtos
->rtos_specific_params
== NULL
)
402 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
404 /* Read the stack pointer */
405 retval
= target_read_buffer(rtos
->target
,
406 thread_id
+ param
->thread_stack_offset
,
407 param
->pointer_width
,
408 (uint8_t *)&stack_ptr
);
409 if (retval
!= ERROR_OK
) {
410 LOG_ERROR("Error reading stack frame from FreeRTOS thread");
413 LOG_DEBUG("FreeRTOS: Read stack pointer at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
414 thread_id
+ param
->thread_stack_offset
,
417 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
420 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
423 *symbol_list
= calloc(
424 ARRAY_SIZE(FreeRTOS_symbol_list
), sizeof(symbol_table_elem_t
));
426 for (i
= 0; i
< ARRAY_SIZE(FreeRTOS_symbol_list
); i
++) {
427 (*symbol_list
)[i
].symbol_name
= FreeRTOS_symbol_list
[i
].name
;
428 (*symbol_list
)[i
].optional
= FreeRTOS_symbol_list
[i
].optional
;
436 static int FreeRTOS_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
441 static int FreeRTOS_get_thread_ascii_info(struct rtos
*rtos
, threadid_t thread_id
, char **info
)
444 const struct FreeRTOS_params
*param
;
452 if (rtos
->rtos_specific_params
== NULL
)
455 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
457 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
458 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
460 /* Read the thread name */
461 retval
= target_read_buffer(rtos
->target
,
462 thread_id
+ param
->thread_name_offset
,
463 FREERTOS_THREAD_NAME_STR_SIZE
,
464 (uint8_t *)&tmp_str
);
465 if (retval
!= ERROR_OK
) {
466 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
469 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
471 if (tmp_str
[0] == '\x00')
472 strcpy(tmp_str
, "No Name");
474 *info
= malloc(strlen(tmp_str
)+1);
475 strcpy(*info
, tmp_str
);
481 static int FreeRTOS_detect_rtos(struct target
*target
)
483 if ((target
->rtos
->symbols
!= NULL
) &&
484 (target
->rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
!= 0)) {
485 /* looks like FreeRTOS */
491 static int FreeRTOS_create(struct target
*target
)
494 while ((i
< FREERTOS_NUM_PARAMS
) &&
495 (0 != strcmp(FreeRTOS_params_list
[i
].target_name
, target
->type
->name
))) {
498 if (i
>= FREERTOS_NUM_PARAMS
) {
499 LOG_ERROR("Could not find target in FreeRTOS compatibility list");
503 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)