1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2011 by Broadcom Corporation *
5 * Evan Hunter - ehunter@broadcom.com *
6 ***************************************************************************/
12 #include <helper/time_support.h>
13 #include <jtag/jtag.h>
14 #include "target/target.h"
15 #include "target/target_type.h"
17 #include "helper/log.h"
18 #include "helper/types.h"
19 #include "rtos_embkernel_stackings.h"
21 #define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64)
23 static bool embkernel_detect_rtos(struct target
*target
);
24 static int embkernel_create(struct target
*target
);
25 static int embkernel_update_threads(struct rtos
*rtos
);
26 static int embkernel_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
,
27 struct rtos_reg
**reg_list
, int *num_regs
);
28 static int embkernel_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[]);
30 const struct rtos_type embkernel_rtos
= {
32 .detect_rtos
= embkernel_detect_rtos
,
33 .create
= embkernel_create
,
34 .update_threads
= embkernel_update_threads
,
35 .get_thread_reg_list
=
36 embkernel_get_thread_reg_list
,
37 .get_symbol_list_to_lookup
= embkernel_get_symbol_list_to_lookup
,
41 SYMBOL_ID_S_CURRENT_TASK
= 0,
42 SYMBOL_ID_S_LIST_READY
= 1,
43 SYMBOL_ID_S_LIST_SLEEP
= 2,
44 SYMBOL_ID_S_LIST_SUSPENDED
= 3,
45 SYMBOL_ID_S_MAX_PRIORITIES
= 4,
46 SYMBOL_ID_S_CURRENT_TASK_COUNT
= 5,
49 static const char * const embkernel_symbol_list
[] = {
53 "Rtos::sListSuspended",
54 "Rtos::sMaxPriorities",
55 "Rtos::sCurrentTaskCount",
58 struct embkernel_params
{
59 const char *target_name
;
60 const unsigned char pointer_width
;
61 const unsigned char thread_count_width
;
62 const unsigned char rtos_list_size
;
63 const unsigned char thread_stack_offset
;
64 const unsigned char thread_name_offset
;
65 const unsigned char thread_priority_offset
;
66 const unsigned char thread_priority_width
;
67 const unsigned char iterable_next_offset
;
68 const unsigned char iterable_task_owner_offset
;
69 const struct rtos_register_stacking
*stacking_info
;
72 static const struct embkernel_params embkernel_params_list
[] = {
74 "cortex_m", /* target_name */
75 4, /* pointer_width */
76 4, /* thread_count_width */
77 8, /*rtos_list_size */
78 0, /*thread_stack_offset */
79 4, /*thread_name_offset */
80 8, /*thread_priority_offset */
81 4, /*thread_priority_width */
82 4, /*iterable_next_offset */
83 12, /*iterable_task_owner_offset */
84 &rtos_embkernel_cortex_m_stacking
, /* stacking_info*/
86 { "hla_target", /* target_name */
87 4, /* pointer_width */
88 4, /* thread_count_width */
89 8, /*rtos_list_size */
90 0, /*thread_stack_offset */
91 4, /*thread_name_offset */
92 8, /*thread_priority_offset */
93 4, /*thread_priority_width */
94 4, /*iterable_next_offset */
95 12, /*iterable_task_owner_offset */
96 &rtos_embkernel_cortex_m_stacking
, /* stacking_info */
100 static bool embkernel_detect_rtos(struct target
*target
)
102 if (target
->rtos
->symbols
) {
103 if (target
->rtos
->symbols
[SYMBOL_ID_S_CURRENT_TASK
].address
!= 0)
109 static int embkernel_create(struct target
*target
)
112 while ((i
< ARRAY_SIZE(embkernel_params_list
)) &&
113 (strcmp(embkernel_params_list
[i
].target_name
, target
->type
->name
) != 0))
116 if (i
>= ARRAY_SIZE(embkernel_params_list
)) {
117 LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
118 "list", target
->type
->name
);
122 target
->rtos
->rtos_specific_params
= (void *) &embkernel_params_list
[i
];
126 static int embkernel_get_tasks_details(struct rtos
*rtos
, int64_t iterable
, const struct embkernel_params
*param
,
127 struct thread_detail
*details
, const char *state_str
)
130 int retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_task_owner_offset
, param
->pointer_width
,
132 if (retval
!= ERROR_OK
)
134 details
->threadid
= (threadid_t
) task
;
135 details
->exists
= true;
137 int64_t name_ptr
= 0;
138 retval
= target_read_buffer(rtos
->target
, task
+ param
->thread_name_offset
, param
->pointer_width
,
139 (uint8_t *) &name_ptr
);
140 if (retval
!= ERROR_OK
)
143 details
->thread_name_str
= malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
);
145 retval
= target_read_buffer(rtos
->target
, name_ptr
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
,
146 (uint8_t *) details
->thread_name_str
);
147 if (retval
!= ERROR_OK
)
149 details
->thread_name_str
[EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
- 1] = 0;
151 snprintf(details
->thread_name_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "NoName:[0x%08X]", (unsigned int) task
);
154 int64_t priority
= 0;
155 retval
= target_read_buffer(rtos
->target
, task
+ param
->thread_priority_offset
, param
->thread_priority_width
,
156 (uint8_t *) &priority
);
157 if (retval
!= ERROR_OK
)
159 details
->extra_info_str
= malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
);
160 if (task
== rtos
->current_thread
) {
161 snprintf(details
->extra_info_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "State: Running, Priority: %u",
162 (unsigned int) priority
);
164 snprintf(details
->extra_info_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "State: %s, Priority: %u",
165 state_str
, (unsigned int) priority
);
168 LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable
,
169 (unsigned int)task
, details
->thread_name_str
);
173 static int embkernel_update_threads(struct rtos
*rtos
)
177 const struct embkernel_params
*param
;
182 if (!rtos
->rtos_specific_params
)
185 if (!rtos
->symbols
) {
186 LOG_ERROR("No symbols for embKernel");
190 if (rtos
->symbols
[SYMBOL_ID_S_CURRENT_TASK
].address
== 0) {
191 LOG_ERROR("Don't have the thread list head");
195 /* wipe out previous thread details if any */
196 rtos_free_threadlist(rtos
);
198 param
= (const struct embkernel_params
*) rtos
->rtos_specific_params
;
200 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_S_CURRENT_TASK
].address
, param
->pointer_width
,
201 (uint8_t *) &rtos
->current_thread
);
202 if (retval
!= ERROR_OK
) {
203 LOG_ERROR("Error reading current thread in embKernel thread list");
207 int64_t max_used_priority
= 0;
208 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_S_MAX_PRIORITIES
].address
, param
->pointer_width
,
209 (uint8_t *) &max_used_priority
);
210 if (retval
!= ERROR_OK
)
213 int thread_list_size
= 0;
214 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_S_CURRENT_TASK_COUNT
].address
,
215 param
->thread_count_width
, (uint8_t *) &thread_list_size
);
217 if (retval
!= ERROR_OK
) {
218 LOG_ERROR("Could not read embKernel thread count from target");
222 /* create space for new thread details */
223 rtos
->thread_details
= malloc(sizeof(struct thread_detail
) * thread_list_size
);
224 if (!rtos
->thread_details
) {
225 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
230 /* Look for ready tasks */
231 for (int pri
= 0; pri
< max_used_priority
; pri
++) {
232 /* Get first item in queue */
233 int64_t iterable
= 0;
234 retval
= target_read_buffer(rtos
->target
,
235 rtos
->symbols
[SYMBOL_ID_S_LIST_READY
].address
+ (pri
* param
->rtos_list_size
), param
->pointer_width
,
236 (uint8_t *) &iterable
);
237 if (retval
!= ERROR_OK
)
239 for (; iterable
&& thread_idx
< thread_list_size
; thread_idx
++) {
240 /* Get info from this iterable item */
241 retval
= embkernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[thread_idx
], "Ready");
242 if (retval
!= ERROR_OK
)
244 /* Get next iterable item */
245 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
246 (uint8_t *) &iterable
);
247 if (retval
!= ERROR_OK
)
251 /* Look for sleeping tasks */
252 int64_t iterable
= 0;
253 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_S_LIST_SLEEP
].address
, param
->pointer_width
,
254 (uint8_t *) &iterable
);
255 if (retval
!= ERROR_OK
)
257 for (; iterable
&& thread_idx
< thread_list_size
; thread_idx
++) {
258 /*Get info from this iterable item */
259 retval
= embkernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[thread_idx
], "Sleeping");
260 if (retval
!= ERROR_OK
)
262 /*Get next iterable item */
263 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
264 (uint8_t *) &iterable
);
265 if (retval
!= ERROR_OK
)
269 /* Look for suspended tasks */
271 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_S_LIST_SUSPENDED
].address
, param
->pointer_width
,
272 (uint8_t *) &iterable
);
273 if (retval
!= ERROR_OK
)
275 for (; iterable
&& thread_idx
< thread_list_size
; thread_idx
++) {
276 /* Get info from this iterable item */
277 retval
= embkernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[thread_idx
], "Suspended");
278 if (retval
!= ERROR_OK
)
280 /*Get next iterable item */
281 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
282 (uint8_t *) &iterable
);
283 if (retval
!= ERROR_OK
)
287 rtos
->thread_count
= 0;
288 rtos
->thread_count
= thread_idx
;
289 LOG_OUTPUT("Found %u tasks\n", (unsigned int)thread_idx
);
293 static int embkernel_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
,
294 struct rtos_reg
**reg_list
, int *num_regs
)
297 const struct embkernel_params
*param
;
298 int64_t stack_ptr
= 0;
306 if (!rtos
->rtos_specific_params
)
309 param
= (const struct embkernel_params
*) rtos
->rtos_specific_params
;
311 /* Read the stack pointer */
312 retval
= target_read_buffer(rtos
->target
, thread_id
+ param
->thread_stack_offset
, param
->pointer_width
,
313 (uint8_t *) &stack_ptr
);
314 if (retval
!= ERROR_OK
) {
315 LOG_ERROR("Error reading stack frame from embKernel thread");
319 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, reg_list
, num_regs
);
322 static int embkernel_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[])
325 *symbol_list
= calloc(ARRAY_SIZE(embkernel_symbol_list
), sizeof(struct symbol_table_elem
));
327 for (i
= 0; i
< ARRAY_SIZE(embkernel_symbol_list
); i
++)
328 (*symbol_list
)[i
].symbol_name
= embkernel_symbol_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)