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 bool 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
,
106 struct rtos_reg
**reg_list
, int *num_regs
);
107 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
109 struct rtos_type FreeRTOS_rtos
= {
112 .detect_rtos
= FreeRTOS_detect_rtos
,
113 .create
= FreeRTOS_create
,
114 .update_threads
= FreeRTOS_update_threads
,
115 .get_thread_reg_list
= FreeRTOS_get_thread_reg_list
,
116 .get_symbol_list_to_lookup
= FreeRTOS_get_symbol_list_to_lookup
,
119 enum FreeRTOS_symbol_values
{
120 FreeRTOS_VAL_pxCurrentTCB
= 0,
121 FreeRTOS_VAL_pxReadyTasksLists
= 1,
122 FreeRTOS_VAL_xDelayedTaskList1
= 2,
123 FreeRTOS_VAL_xDelayedTaskList2
= 3,
124 FreeRTOS_VAL_pxDelayedTaskList
= 4,
125 FreeRTOS_VAL_pxOverflowDelayedTaskList
= 5,
126 FreeRTOS_VAL_xPendingReadyList
= 6,
127 FreeRTOS_VAL_xTasksWaitingTermination
= 7,
128 FreeRTOS_VAL_xSuspendedTaskList
= 8,
129 FreeRTOS_VAL_uxCurrentNumberOfTasks
= 9,
130 FreeRTOS_VAL_uxTopUsedPriority
= 10,
138 static const struct symbols FreeRTOS_symbol_list
[] = {
139 { "pxCurrentTCB", false },
140 { "pxReadyTasksLists", false },
141 { "xDelayedTaskList1", false },
142 { "xDelayedTaskList2", false },
143 { "pxDelayedTaskList", false },
144 { "pxOverflowDelayedTaskList", false },
145 { "xPendingReadyList", false },
146 { "xTasksWaitingTermination", true }, /* Only if INCLUDE_vTaskDelete */
147 { "xSuspendedTaskList", true }, /* Only if INCLUDE_vTaskSuspend */
148 { "uxCurrentNumberOfTasks", false },
149 { "uxTopUsedPriority", true }, /* Unavailable since v7.5.3 */
154 /* this is not safe for little endian yet */
155 /* may be problems reading if sizes are not 32 bit long integers. */
156 /* test mallocs for failure */
158 static int FreeRTOS_update_threads(struct rtos
*rtos
)
163 const struct FreeRTOS_params
*param
;
165 if (rtos
->rtos_specific_params
== NULL
)
168 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
170 if (rtos
->symbols
== NULL
) {
171 LOG_ERROR("No symbols for FreeRTOS");
175 if (rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
== 0) {
176 LOG_ERROR("Don't have the number of threads in FreeRTOS");
180 int thread_list_size
= 0;
181 retval
= target_read_buffer(rtos
->target
,
182 rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
,
183 param
->thread_count_width
,
184 (uint8_t *)&thread_list_size
);
185 LOG_DEBUG("FreeRTOS: Read uxCurrentNumberOfTasks at 0x%" PRIx64
", value %d\r\n",
186 rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
,
189 if (retval
!= ERROR_OK
) {
190 LOG_ERROR("Could not read FreeRTOS thread count from target");
194 /* wipe out previous thread details if any */
195 rtos_free_threadlist(rtos
);
197 /* read the current thread */
198 retval
= target_read_buffer(rtos
->target
,
199 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
200 param
->pointer_width
,
201 (uint8_t *)&rtos
->current_thread
);
202 if (retval
!= ERROR_OK
) {
203 LOG_ERROR("Error reading current thread in FreeRTOS thread list");
206 LOG_DEBUG("FreeRTOS: Read pxCurrentTCB at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
207 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
208 rtos
->current_thread
);
210 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
211 /* Either : No RTOS threads - there is always at least the current execution though */
212 /* OR : No current thread - all threads suspended - show the current execution
214 char tmp_str
[] = "Current Execution";
217 rtos
->thread_details
= malloc(
218 sizeof(struct thread_detail
) * thread_list_size
);
219 if (!rtos
->thread_details
) {
220 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
223 rtos
->thread_details
->threadid
= 1;
224 rtos
->thread_details
->exists
= true;
225 rtos
->thread_details
->extra_info_str
= NULL
;
226 rtos
->thread_details
->thread_name_str
= malloc(sizeof(tmp_str
));
227 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
229 if (thread_list_size
== 1) {
230 rtos
->thread_count
= 1;
234 /* create space for new thread details */
235 rtos
->thread_details
= malloc(
236 sizeof(struct thread_detail
) * thread_list_size
);
237 if (!rtos
->thread_details
) {
238 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
243 /* Find out how many lists are needed to be read from pxReadyTasksLists, */
244 if (rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
== 0) {
245 LOG_ERROR("FreeRTOS: uxTopUsedPriority is not defined, consult the OpenOCD manual for a work-around");
248 int64_t max_used_priority
= 0;
249 retval
= target_read_buffer(rtos
->target
,
250 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
251 param
->pointer_width
,
252 (uint8_t *)&max_used_priority
);
253 if (retval
!= ERROR_OK
)
255 LOG_DEBUG("FreeRTOS: Read uxTopUsedPriority at 0x%" PRIx64
", value %" PRId64
"\r\n",
256 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
258 if (max_used_priority
> FREERTOS_MAX_PRIORITIES
) {
259 LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64
"",
264 symbol_address_t
*list_of_lists
=
265 malloc(sizeof(symbol_address_t
) *
266 (max_used_priority
+1 + 5));
267 if (!list_of_lists
) {
268 LOG_ERROR("Error allocating memory for %" PRId64
" priorities", max_used_priority
);
273 for (num_lists
= 0; num_lists
<= max_used_priority
; num_lists
++)
274 list_of_lists
[num_lists
] = rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
+
275 num_lists
* param
->list_width
;
277 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList1
].address
;
278 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList2
].address
;
279 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xPendingReadyList
].address
;
280 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xSuspendedTaskList
].address
;
281 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xTasksWaitingTermination
].address
;
283 for (i
= 0; i
< num_lists
; i
++) {
284 if (list_of_lists
[i
] == 0)
287 /* Read the number of threads in this list */
288 int64_t list_thread_count
= 0;
289 retval
= target_read_buffer(rtos
->target
,
291 param
->thread_count_width
,
292 (uint8_t *)&list_thread_count
);
293 if (retval
!= ERROR_OK
) {
294 LOG_ERROR("Error reading number of threads in FreeRTOS thread list");
298 LOG_DEBUG("FreeRTOS: Read thread count for list %d at 0x%" PRIx64
", value %" PRId64
"\r\n",
299 i
, list_of_lists
[i
], list_thread_count
);
301 if (list_thread_count
== 0)
304 /* Read the location of first list item */
305 uint64_t prev_list_elem_ptr
= -1;
306 uint64_t list_elem_ptr
= 0;
307 retval
= target_read_buffer(rtos
->target
,
308 list_of_lists
[i
] + param
->list_next_offset
,
309 param
->pointer_width
,
310 (uint8_t *)&list_elem_ptr
);
311 if (retval
!= ERROR_OK
) {
312 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
316 LOG_DEBUG("FreeRTOS: Read first item for list %d at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
317 i
, list_of_lists
[i
] + param
->list_next_offset
, list_elem_ptr
);
319 while ((list_thread_count
> 0) && (list_elem_ptr
!= 0) &&
320 (list_elem_ptr
!= prev_list_elem_ptr
) &&
321 (tasks_found
< thread_list_size
)) {
322 /* Get the location of the thread structure. */
323 rtos
->thread_details
[tasks_found
].threadid
= 0;
324 retval
= target_read_buffer(rtos
->target
,
325 list_elem_ptr
+ param
->list_elem_content_offset
,
326 param
->pointer_width
,
327 (uint8_t *)&(rtos
->thread_details
[tasks_found
].threadid
));
328 if (retval
!= ERROR_OK
) {
329 LOG_ERROR("Error reading thread list item object in FreeRTOS thread list");
333 LOG_DEBUG("FreeRTOS: Read Thread ID at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
334 list_elem_ptr
+ param
->list_elem_content_offset
,
335 rtos
->thread_details
[tasks_found
].threadid
);
337 /* get thread name */
339 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
340 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
342 /* Read the thread name */
343 retval
= target_read_buffer(rtos
->target
,
344 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
345 FREERTOS_THREAD_NAME_STR_SIZE
,
346 (uint8_t *)&tmp_str
);
347 if (retval
!= ERROR_OK
) {
348 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
352 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
353 LOG_DEBUG("FreeRTOS: Read Thread Name at 0x%" PRIx64
", value \"%s\"\r\n",
354 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
357 if (tmp_str
[0] == '\x00')
358 strcpy(tmp_str
, "No Name");
360 rtos
->thread_details
[tasks_found
].thread_name_str
=
361 malloc(strlen(tmp_str
)+1);
362 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
363 rtos
->thread_details
[tasks_found
].exists
= true;
365 if (rtos
->thread_details
[tasks_found
].threadid
== rtos
->current_thread
) {
366 char running_str
[] = "State: Running";
367 rtos
->thread_details
[tasks_found
].extra_info_str
= malloc(
368 sizeof(running_str
));
369 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
,
372 rtos
->thread_details
[tasks_found
].extra_info_str
= NULL
;
377 prev_list_elem_ptr
= list_elem_ptr
;
379 retval
= target_read_buffer(rtos
->target
,
380 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
381 param
->pointer_width
,
382 (uint8_t *)&list_elem_ptr
);
383 if (retval
!= ERROR_OK
) {
384 LOG_ERROR("Error reading next thread item location in FreeRTOS thread list");
388 LOG_DEBUG("FreeRTOS: Read next thread location at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
389 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
395 rtos
->thread_count
= tasks_found
;
399 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
,
400 struct rtos_reg
**reg_list
, int *num_regs
)
403 const struct FreeRTOS_params
*param
;
404 int64_t stack_ptr
= 0;
412 if (rtos
->rtos_specific_params
== NULL
)
415 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
417 /* Read the stack pointer */
418 retval
= target_read_buffer(rtos
->target
,
419 thread_id
+ param
->thread_stack_offset
,
420 param
->pointer_width
,
421 (uint8_t *)&stack_ptr
);
422 if (retval
!= ERROR_OK
) {
423 LOG_ERROR("Error reading stack frame from FreeRTOS thread");
426 LOG_DEBUG("FreeRTOS: Read stack pointer at 0x%" PRIx64
", value 0x%" PRIx64
"\r\n",
427 thread_id
+ param
->thread_stack_offset
,
430 /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */
431 int cm4_fpu_enabled
= 0;
432 struct armv7m_common
*armv7m_target
= target_to_armv7m(rtos
->target
);
433 if (is_armv7m(armv7m_target
)) {
434 if (armv7m_target
->fp_feature
== FPv4_SP
) {
435 /* Found ARM v7m target which includes a FPU */
438 retval
= target_read_u32(rtos
->target
, FPU_CPACR
, &cpacr
);
439 if (retval
!= ERROR_OK
) {
440 LOG_ERROR("Could not read CPACR register to check FPU state");
444 /* Check if CP10 and CP11 are set to full access. */
445 if (cpacr
& 0x00F00000) {
446 /* Found target with enabled FPU */
452 if (cm4_fpu_enabled
== 1) {
453 /* Read the LR to decide between stacking with or without FPU */
455 retval
= target_read_buffer(rtos
->target
,
457 param
->pointer_width
,
459 if (retval
!= ERROR_OK
) {
460 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
463 if ((LR_svc
& 0x10) == 0)
464 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info_cm4f_fpu
, stack_ptr
, reg_list
, num_regs
);
466 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info_cm4f
, stack_ptr
, reg_list
, num_regs
);
468 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info_cm3
, stack_ptr
, reg_list
, num_regs
);
471 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
474 *symbol_list
= calloc(
475 ARRAY_SIZE(FreeRTOS_symbol_list
), sizeof(symbol_table_elem_t
));
477 for (i
= 0; i
< ARRAY_SIZE(FreeRTOS_symbol_list
); i
++) {
478 (*symbol_list
)[i
].symbol_name
= FreeRTOS_symbol_list
[i
].name
;
479 (*symbol_list
)[i
].optional
= FreeRTOS_symbol_list
[i
].optional
;
487 static int FreeRTOS_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
492 static int FreeRTOS_get_thread_ascii_info(struct rtos
*rtos
, threadid_t thread_id
, char **info
)
495 const struct FreeRTOS_params
*param
;
503 if (rtos
->rtos_specific_params
== NULL
)
506 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
508 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
509 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
511 /* Read the thread name */
512 retval
= target_read_buffer(rtos
->target
,
513 thread_id
+ param
->thread_name_offset
,
514 FREERTOS_THREAD_NAME_STR_SIZE
,
515 (uint8_t *)&tmp_str
);
516 if (retval
!= ERROR_OK
) {
517 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
520 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
522 if (tmp_str
[0] == '\x00')
523 strcpy(tmp_str
, "No Name");
525 *info
= malloc(strlen(tmp_str
)+1);
526 strcpy(*info
, tmp_str
);
532 static bool FreeRTOS_detect_rtos(struct target
*target
)
534 if ((target
->rtos
->symbols
!= NULL
) &&
535 (target
->rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
!= 0)) {
536 /* looks like FreeRTOS */
542 static int FreeRTOS_create(struct target
*target
)
545 while ((i
< FREERTOS_NUM_PARAMS
) &&
546 (0 != strcmp(FreeRTOS_params_list
[i
].target_name
, target
->type
->name
))) {
549 if (i
>= FREERTOS_NUM_PARAMS
) {
550 LOG_ERROR("Could not find target in FreeRTOS compatibility list");
554 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)