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, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
23 #include <helper/time_support.h>
24 #include <jtag/jtag.h>
25 #include "target/target.h"
26 #include "target/target_type.h"
28 #include "helper/log.h"
29 #include "helper/types.h"
30 #include "rtos_standard_stackings.h"
31 #include "target/armv7m.h"
32 #include "target/cortex_m.h"
36 #define FREERTOS_MAX_PRIORITIES 63
38 #define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset)
40 struct FreeRTOS_params
{
41 const char *target_name
;
42 const unsigned char thread_count_width
;
43 const unsigned char pointer_width
;
44 const unsigned char list_next_offset
;
45 const unsigned char list_width
;
46 const unsigned char list_elem_next_offset
;
47 const unsigned char list_elem_content_offset
;
48 const unsigned char thread_stack_offset
;
49 const unsigned char thread_name_offset
;
50 const struct rtos_register_stacking
*stacking_info_cm3
;
51 const struct rtos_register_stacking
*stacking_info_cm4f
;
52 const struct rtos_register_stacking
*stacking_info_cm4f_fpu
;
55 static const struct FreeRTOS_params FreeRTOS_params_list
[] = {
57 "cortex_m", /* target_name */
58 4, /* thread_count_width; */
59 4, /* pointer_width; */
60 16, /* list_next_offset; */
62 8, /* list_elem_next_offset; */
63 12, /* list_elem_content_offset */
64 0, /* thread_stack_offset; */
65 52, /* thread_name_offset; */
66 &rtos_standard_Cortex_M3_stacking
, /* stacking_info */
67 &rtos_standard_Cortex_M4F_stacking
,
68 &rtos_standard_Cortex_M4F_FPU_stacking
,
71 "hla_target", /* target_name */
72 4, /* thread_count_width; */
73 4, /* pointer_width; */
74 16, /* list_next_offset; */
76 8, /* list_elem_next_offset; */
77 12, /* list_elem_content_offset */
78 0, /* thread_stack_offset; */
79 52, /* thread_name_offset; */
80 &rtos_standard_Cortex_M3_stacking
, /* stacking_info */
81 &rtos_standard_Cortex_M4F_stacking
,
82 &rtos_standard_Cortex_M4F_FPU_stacking
,
85 "nds32_v3", /* target_name */
86 4, /* thread_count_width; */
87 4, /* pointer_width; */
88 16, /* list_next_offset; */
90 8, /* list_elem_next_offset; */
91 12, /* list_elem_content_offset */
92 0, /* thread_stack_offset; */
93 52, /* thread_name_offset; */
94 &rtos_standard_NDS32_N1068_stacking
, /* stacking_info */
95 &rtos_standard_Cortex_M4F_stacking
,
96 &rtos_standard_Cortex_M4F_FPU_stacking
,
100 #define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
102 static int FreeRTOS_detect_rtos(struct target
*target
);
103 static int FreeRTOS_create(struct target
*target
);
104 static int FreeRTOS_update_threads(struct rtos
*rtos
);
105 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
);
106 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
108 struct rtos_type FreeRTOS_rtos
= {
111 .detect_rtos
= FreeRTOS_detect_rtos
,
112 .create
= FreeRTOS_create
,
113 .update_threads
= FreeRTOS_update_threads
,
114 .get_thread_reg_list
= FreeRTOS_get_thread_reg_list
,
115 .get_symbol_list_to_lookup
= FreeRTOS_get_symbol_list_to_lookup
,
118 enum FreeRTOS_symbol_values
{
119 FreeRTOS_VAL_pxCurrentTCB
= 0,
120 FreeRTOS_VAL_pxReadyTasksLists
= 1,
121 FreeRTOS_VAL_xDelayedTaskList1
= 2,
122 FreeRTOS_VAL_xDelayedTaskList2
= 3,
123 FreeRTOS_VAL_pxDelayedTaskList
= 4,
124 FreeRTOS_VAL_pxOverflowDelayedTaskList
= 5,
125 FreeRTOS_VAL_xPendingReadyList
= 6,
126 FreeRTOS_VAL_xTasksWaitingTermination
= 7,
127 FreeRTOS_VAL_xSuspendedTaskList
= 8,
128 FreeRTOS_VAL_uxCurrentNumberOfTasks
= 9,
129 FreeRTOS_VAL_uxTopUsedPriority
= 10,
137 static const struct symbols FreeRTOS_symbol_list
[] = {
138 { "pxCurrentTCB", false },
139 { "pxReadyTasksLists", false },
140 { "xDelayedTaskList1", false },
141 { "xDelayedTaskList2", false },
142 { "pxDelayedTaskList", false },
143 { "pxOverflowDelayedTaskList", false },
144 { "xPendingReadyList", false },
145 { "xTasksWaitingTermination", true }, /* Only if INCLUDE_vTaskDelete */
146 { "xSuspendedTaskList", true }, /* Only if INCLUDE_vTaskSuspend */
147 { "uxCurrentNumberOfTasks", false },
148 { "uxTopUsedPriority", true }, /* Unavailable since v7.5.3 */
153 /* this is not safe for little endian yet */
154 /* may be problems reading if sizes are not 32 bit long integers. */
155 /* test mallocs for failure */
157 static int FreeRTOS_update_threads(struct rtos
*rtos
)
162 const struct FreeRTOS_params
*param
;
164 if (rtos
->rtos_specific_params
== NULL
)
167 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
169 if (rtos
->symbols
== NULL
) {
170 LOG_ERROR("No symbols for FreeRTOS");
174 if (rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
== 0) {
175 LOG_ERROR("Don't have the number of threads in FreeRTOS");
179 int thread_list_size
= 0;
180 retval
= target_read_buffer(rtos
->target
,
181 rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
,
182 param
->thread_count_width
,
183 (uint8_t *)&thread_list_size
);
184 LOG_DEBUG("FreeRTOS: Read uxCurrentNumberOfTasks at 0x%" PRIx64
", value %d\r\n",
185 rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
,
188 if (retval
!= ERROR_OK
) {
189 LOG_ERROR("Could not read FreeRTOS thread count from target");
193 /* wipe out previous thread details if any */
194 rtos_free_threadlist(rtos
);
196 /* read the current thread */
197 retval
= target_read_buffer(rtos
->target
,
198 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
199 param
->pointer_width
,
200 (uint8_t *)&rtos
->current_thread
);
201 if (retval
!= ERROR_OK
) {
202 LOG_ERROR("Error reading current thread in FreeRTOS thread list");
205 LOG_DEBUG("FreeRTOS: Read pxCurrentTCB at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
206 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
207 rtos
->current_thread
);
209 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
210 /* Either : No RTOS threads - there is always at least the current execution though */
211 /* OR : No current thread - all threads suspended - show the current execution
213 char tmp_str
[] = "Current Execution";
216 rtos
->thread_details
= malloc(
217 sizeof(struct thread_detail
) * thread_list_size
);
218 if (!rtos
->thread_details
) {
219 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
222 rtos
->thread_details
->threadid
= 1;
223 rtos
->thread_details
->exists
= true;
224 rtos
->thread_details
->extra_info_str
= NULL
;
225 rtos
->thread_details
->thread_name_str
= malloc(sizeof(tmp_str
));
226 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
228 if (thread_list_size
== 1) {
229 rtos
->thread_count
= 1;
233 /* create space for new thread details */
234 rtos
->thread_details
= malloc(
235 sizeof(struct thread_detail
) * thread_list_size
);
236 if (!rtos
->thread_details
) {
237 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
242 /* Find out how many lists are needed to be read from pxReadyTasksLists, */
243 if (rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
== 0) {
244 LOG_ERROR("FreeRTOS: uxTopUsedPriority is not defined, consult the OpenOCD manual for a work-around");
247 int64_t max_used_priority
= 0;
248 retval
= target_read_buffer(rtos
->target
,
249 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
250 param
->pointer_width
,
251 (uint8_t *)&max_used_priority
);
252 if (retval
!= ERROR_OK
)
254 LOG_DEBUG("FreeRTOS: Read uxTopUsedPriority at 0x%" PRIx64
", value %" PRId64
"\r\n",
255 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
257 if (max_used_priority
> FREERTOS_MAX_PRIORITIES
) {
258 LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64
"",
263 symbol_address_t
*list_of_lists
=
264 malloc(sizeof(symbol_address_t
) *
265 (max_used_priority
+1 + 5));
266 if (!list_of_lists
) {
267 LOG_ERROR("Error allocating memory for %" PRId64
" priorities", max_used_priority
);
272 for (num_lists
= 0; num_lists
<= max_used_priority
; num_lists
++)
273 list_of_lists
[num_lists
] = rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
+
274 num_lists
* param
->list_width
;
276 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList1
].address
;
277 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList2
].address
;
278 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xPendingReadyList
].address
;
279 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xSuspendedTaskList
].address
;
280 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xTasksWaitingTermination
].address
;
282 for (i
= 0; i
< num_lists
; i
++) {
283 if (list_of_lists
[i
] == 0)
286 /* Read the number of threads in this list */
287 int64_t list_thread_count
= 0;
288 retval
= target_read_buffer(rtos
->target
,
290 param
->thread_count_width
,
291 (uint8_t *)&list_thread_count
);
292 if (retval
!= ERROR_OK
) {
293 LOG_ERROR("Error reading number of threads in FreeRTOS thread list");
297 LOG_DEBUG("FreeRTOS: Read thread count for list %d at 0x%" PRIx64
", value %" PRId64
"\r\n",
298 i
, list_of_lists
[i
], list_thread_count
);
300 if (list_thread_count
== 0)
303 /* Read the location of first list item */
304 uint64_t prev_list_elem_ptr
= -1;
305 uint64_t list_elem_ptr
= 0;
306 retval
= target_read_buffer(rtos
->target
,
307 list_of_lists
[i
] + param
->list_next_offset
,
308 param
->pointer_width
,
309 (uint8_t *)&list_elem_ptr
);
310 if (retval
!= ERROR_OK
) {
311 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
315 LOG_DEBUG("FreeRTOS: Read first item for list %d at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
316 i
, list_of_lists
[i
] + param
->list_next_offset
, list_elem_ptr
);
318 while ((list_thread_count
> 0) && (list_elem_ptr
!= 0) &&
319 (list_elem_ptr
!= prev_list_elem_ptr
) &&
320 (tasks_found
< thread_list_size
)) {
321 /* Get the location of the thread structure. */
322 rtos
->thread_details
[tasks_found
].threadid
= 0;
323 retval
= target_read_buffer(rtos
->target
,
324 list_elem_ptr
+ param
->list_elem_content_offset
,
325 param
->pointer_width
,
326 (uint8_t *)&(rtos
->thread_details
[tasks_found
].threadid
));
327 if (retval
!= ERROR_OK
) {
328 LOG_ERROR("Error reading thread list item object in FreeRTOS thread list");
332 LOG_DEBUG("FreeRTOS: Read Thread ID at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
333 list_elem_ptr
+ param
->list_elem_content_offset
,
334 rtos
->thread_details
[tasks_found
].threadid
);
336 /* get thread name */
338 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
339 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
341 /* Read the thread name */
342 retval
= target_read_buffer(rtos
->target
,
343 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
344 FREERTOS_THREAD_NAME_STR_SIZE
,
345 (uint8_t *)&tmp_str
);
346 if (retval
!= ERROR_OK
) {
347 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
351 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
352 LOG_DEBUG("FreeRTOS: Read Thread Name at 0x%" PRIx64
", value \"%s\"\r\n",
353 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
356 if (tmp_str
[0] == '\x00')
357 strcpy(tmp_str
, "No Name");
359 rtos
->thread_details
[tasks_found
].thread_name_str
=
360 malloc(strlen(tmp_str
)+1);
361 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
362 rtos
->thread_details
[tasks_found
].exists
= true;
364 if (rtos
->thread_details
[tasks_found
].threadid
== rtos
->current_thread
) {
365 char running_str
[] = "Running";
366 rtos
->thread_details
[tasks_found
].extra_info_str
= malloc(
367 sizeof(running_str
));
368 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
,
371 rtos
->thread_details
[tasks_found
].extra_info_str
= NULL
;
376 prev_list_elem_ptr
= list_elem_ptr
;
378 retval
= target_read_buffer(rtos
->target
,
379 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
380 param
->pointer_width
,
381 (uint8_t *)&list_elem_ptr
);
382 if (retval
!= ERROR_OK
) {
383 LOG_ERROR("Error reading next thread item location in FreeRTOS thread list");
387 LOG_DEBUG("FreeRTOS: Read next thread location at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
388 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
394 rtos
->thread_count
= tasks_found
;
398 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
401 const struct FreeRTOS_params
*param
;
402 int64_t stack_ptr
= 0;
404 *hex_reg_list
= NULL
;
411 if (rtos
->rtos_specific_params
== NULL
)
414 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
416 /* Read the stack pointer */
417 retval
= target_read_buffer(rtos
->target
,
418 thread_id
+ param
->thread_stack_offset
,
419 param
->pointer_width
,
420 (uint8_t *)&stack_ptr
);
421 if (retval
!= ERROR_OK
) {
422 LOG_ERROR("Error reading stack frame from FreeRTOS thread");
425 LOG_DEBUG("FreeRTOS: Read stack pointer at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
426 thread_id
+ param
->thread_stack_offset
,
429 /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */
430 int cm4_fpu_enabled
= 0;
431 struct armv7m_common
*armv7m_target
= target_to_armv7m(rtos
->target
);
432 if (is_armv7m(armv7m_target
)) {
433 if (armv7m_target
->fp_feature
== FPv4_SP
) {
434 /* Found ARM v7m target which includes a FPU */
437 retval
= target_read_u32(rtos
->target
, FPU_CPACR
, &cpacr
);
438 if (retval
!= ERROR_OK
) {
439 LOG_ERROR("Could not read CPACR register to check FPU state");
443 /* Check if CP10 and CP11 are set to full access. */
444 if (cpacr
& 0x00F00000) {
445 /* Found target with enabled FPU */
451 if (cm4_fpu_enabled
== 1) {
452 /* Read the LR to decide between stacking with or without FPU */
454 retval
= target_read_buffer(rtos
->target
,
456 param
->pointer_width
,
458 if (retval
!= ERROR_OK
) {
459 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
462 if ((LR_svc
& 0x10) == 0)
463 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info_cm4f_fpu
, stack_ptr
, hex_reg_list
);
465 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info_cm4f
, stack_ptr
, hex_reg_list
);
467 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info_cm3
, stack_ptr
, hex_reg_list
);
470 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
473 *symbol_list
= calloc(
474 ARRAY_SIZE(FreeRTOS_symbol_list
), sizeof(symbol_table_elem_t
));
476 for (i
= 0; i
< ARRAY_SIZE(FreeRTOS_symbol_list
); i
++) {
477 (*symbol_list
)[i
].symbol_name
= FreeRTOS_symbol_list
[i
].name
;
478 (*symbol_list
)[i
].optional
= FreeRTOS_symbol_list
[i
].optional
;
486 static int FreeRTOS_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
491 static int FreeRTOS_get_thread_ascii_info(struct rtos
*rtos
, threadid_t thread_id
, char **info
)
494 const struct FreeRTOS_params
*param
;
502 if (rtos
->rtos_specific_params
== NULL
)
505 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
507 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
508 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
510 /* Read the thread name */
511 retval
= target_read_buffer(rtos
->target
,
512 thread_id
+ param
->thread_name_offset
,
513 FREERTOS_THREAD_NAME_STR_SIZE
,
514 (uint8_t *)&tmp_str
);
515 if (retval
!= ERROR_OK
) {
516 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
519 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
521 if (tmp_str
[0] == '\x00')
522 strcpy(tmp_str
, "No Name");
524 *info
= malloc(strlen(tmp_str
)+1);
525 strcpy(*info
, tmp_str
);
531 static int FreeRTOS_detect_rtos(struct target
*target
)
533 if ((target
->rtos
->symbols
!= NULL
) &&
534 (target
->rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
!= 0)) {
535 /* looks like FreeRTOS */
541 static int FreeRTOS_create(struct target
*target
)
544 while ((i
< FREERTOS_NUM_PARAMS
) &&
545 (0 != strcmp(FreeRTOS_params_list
[i
].target_name
, target
->type
->name
))) {
548 if (i
>= FREERTOS_NUM_PARAMS
) {
549 LOG_ERROR("Could not find target in FreeRTOS compatibility list");
553 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)