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 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 char *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
);
170 if (retval
!= ERROR_OK
) {
171 LOG_ERROR("Could not read FreeRTOS thread count from target");
175 /* wipe out previous thread details if any */
176 rtos_free_threadlist(rtos
);
178 /* read the current thread */
179 retval
= target_read_buffer(rtos
->target
,
180 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
181 param
->pointer_width
,
182 (uint8_t *)&rtos
->current_thread
);
183 if (retval
!= ERROR_OK
) {
184 LOG_ERROR("Error reading current thread in FreeRTOS thread list");
188 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
189 /* Either : No RTOS threads - there is always at least the current execution though */
190 /* OR : No current thread - all threads suspended - show the current execution
192 char tmp_str
[] = "Current Execution";
195 rtos
->thread_details
= malloc(
196 sizeof(struct thread_detail
) * thread_list_size
);
197 if (!rtos
->thread_details
) {
198 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
201 rtos
->thread_details
->threadid
= 1;
202 rtos
->thread_details
->exists
= true;
203 rtos
->thread_details
->display_str
= NULL
;
204 rtos
->thread_details
->extra_info_str
= NULL
;
205 rtos
->thread_details
->thread_name_str
= malloc(sizeof(tmp_str
));
206 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
208 if (thread_list_size
== 1) {
209 rtos
->thread_count
= 1;
213 /* create space for new thread details */
214 rtos
->thread_details
= malloc(
215 sizeof(struct thread_detail
) * thread_list_size
);
216 if (!rtos
->thread_details
) {
217 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
222 /* Find out how many lists are needed to be read from pxReadyTasksLists, */
223 int64_t max_used_priority
= 0;
224 retval
= target_read_buffer(rtos
->target
,
225 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
226 param
->pointer_width
,
227 (uint8_t *)&max_used_priority
);
228 if (retval
!= ERROR_OK
)
230 if (max_used_priority
> FREERTOS_MAX_PRIORITIES
) {
231 LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64
"",
236 symbol_address_t
*list_of_lists
=
237 malloc(sizeof(symbol_address_t
) *
238 (max_used_priority
+1 + 5));
239 if (!list_of_lists
) {
240 LOG_ERROR("Error allocating memory for %" PRId64
" priorities", max_used_priority
);
245 for (num_lists
= 0; num_lists
<= max_used_priority
; num_lists
++)
246 list_of_lists
[num_lists
] = rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
+
247 num_lists
* param
->list_width
;
249 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList1
].address
;
250 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList2
].address
;
251 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xPendingReadyList
].address
;
252 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xSuspendedTaskList
].address
;
253 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xTasksWaitingTermination
].address
;
255 for (i
= 0; i
< num_lists
; i
++) {
256 if (list_of_lists
[i
] == 0)
259 /* Read the number of threads in this list */
260 int64_t list_thread_count
= 0;
261 retval
= target_read_buffer(rtos
->target
,
263 param
->thread_count_width
,
264 (uint8_t *)&list_thread_count
);
265 if (retval
!= ERROR_OK
) {
266 LOG_ERROR("Error reading number of threads in FreeRTOS thread list");
271 if (list_thread_count
== 0)
274 /* Read the location of first list item */
275 uint64_t prev_list_elem_ptr
= -1;
276 uint64_t list_elem_ptr
= 0;
277 retval
= target_read_buffer(rtos
->target
,
278 list_of_lists
[i
] + param
->list_next_offset
,
279 param
->pointer_width
,
280 (uint8_t *)&list_elem_ptr
);
281 if (retval
!= ERROR_OK
) {
282 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
287 while ((list_thread_count
> 0) && (list_elem_ptr
!= 0) &&
288 (list_elem_ptr
!= prev_list_elem_ptr
) &&
289 (tasks_found
< thread_list_size
)) {
290 /* Get the location of the thread structure. */
291 rtos
->thread_details
[tasks_found
].threadid
= 0;
292 retval
= target_read_buffer(rtos
->target
,
293 list_elem_ptr
+ param
->list_elem_content_offset
,
294 param
->pointer_width
,
295 (uint8_t *)&(rtos
->thread_details
[tasks_found
].threadid
));
296 if (retval
!= ERROR_OK
) {
297 LOG_ERROR("Error reading thread list item object in FreeRTOS thread list");
302 /* get thread name */
304 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
305 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
307 /* Read the thread name */
308 retval
= target_read_buffer(rtos
->target
,
309 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
310 FREERTOS_THREAD_NAME_STR_SIZE
,
311 (uint8_t *)&tmp_str
);
312 if (retval
!= ERROR_OK
) {
313 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
317 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
319 if (tmp_str
[0] == '\x00')
320 strcpy(tmp_str
, "No Name");
322 rtos
->thread_details
[tasks_found
].thread_name_str
=
323 malloc(strlen(tmp_str
)+1);
324 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
325 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
326 rtos
->thread_details
[tasks_found
].exists
= true;
328 if (rtos
->thread_details
[tasks_found
].threadid
== rtos
->current_thread
) {
329 char running_str
[] = "Running";
330 rtos
->thread_details
[tasks_found
].extra_info_str
= malloc(
331 sizeof(running_str
));
332 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
,
335 rtos
->thread_details
[tasks_found
].extra_info_str
= NULL
;
340 prev_list_elem_ptr
= list_elem_ptr
;
342 retval
= target_read_buffer(rtos
->target
,
343 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
344 param
->pointer_width
,
345 (uint8_t *)&list_elem_ptr
);
346 if (retval
!= ERROR_OK
) {
347 LOG_ERROR("Error reading next thread item location in FreeRTOS thread list");
355 rtos
->thread_count
= tasks_found
;
359 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
362 const struct FreeRTOS_params
*param
;
363 int64_t stack_ptr
= 0;
365 *hex_reg_list
= NULL
;
372 if (rtos
->rtos_specific_params
== NULL
)
375 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
377 /* Read the stack pointer */
378 retval
= target_read_buffer(rtos
->target
,
379 thread_id
+ param
->thread_stack_offset
,
380 param
->pointer_width
,
381 (uint8_t *)&stack_ptr
);
382 if (retval
!= ERROR_OK
) {
383 LOG_ERROR("Error reading stack frame from FreeRTOS thread");
387 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
390 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
393 *symbol_list
= malloc(
394 sizeof(symbol_table_elem_t
) * ARRAY_SIZE(FreeRTOS_symbol_list
));
396 for (i
= 0; i
< ARRAY_SIZE(FreeRTOS_symbol_list
); i
++)
397 (*symbol_list
)[i
].symbol_name
= FreeRTOS_symbol_list
[i
];
404 static int FreeRTOS_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
409 static int FreeRTOS_get_thread_ascii_info(struct rtos
*rtos
, threadid_t thread_id
, char **info
)
412 const struct FreeRTOS_params
*param
;
420 if (rtos
->rtos_specific_params
== NULL
)
423 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
425 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
426 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
428 /* Read the thread name */
429 retval
= target_read_buffer(rtos
->target
,
430 thread_id
+ param
->thread_name_offset
,
431 FREERTOS_THREAD_NAME_STR_SIZE
,
432 (uint8_t *)&tmp_str
);
433 if (retval
!= ERROR_OK
) {
434 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
437 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
439 if (tmp_str
[0] == '\x00')
440 strcpy(tmp_str
, "No Name");
442 *info
= malloc(strlen(tmp_str
)+1);
443 strcpy(*info
, tmp_str
);
449 static int FreeRTOS_detect_rtos(struct target
*target
)
451 if ((target
->rtos
->symbols
!= NULL
) &&
452 (target
->rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
!= 0)) {
453 /* looks like FreeRTOS */
459 static int FreeRTOS_create(struct target
*target
)
462 while ((i
< FREERTOS_NUM_PARAMS
) &&
463 (0 != strcmp(FreeRTOS_params_list
[i
].target_name
, target
->type
->name
))) {
466 if (i
>= FREERTOS_NUM_PARAMS
) {
467 LOG_ERROR("Could not find target in FreeRTOS compatibility list");
471 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)