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_embkernel_stackings.h"
32 #define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64)
34 static bool embKernel_detect_rtos(struct target
*target
);
35 static int embKernel_create(struct target
*target
);
36 static int embKernel_update_threads(struct rtos
*rtos
);
37 static int embKernel_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
,
38 struct rtos_reg
**reg_list
, int *num_regs
);
39 static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
41 struct rtos_type embKernel_rtos
= {
43 .detect_rtos
= embKernel_detect_rtos
,
44 .create
= embKernel_create
,
45 .update_threads
= embKernel_update_threads
,
46 .get_thread_reg_list
=
47 embKernel_get_thread_reg_list
,
48 .get_symbol_list_to_lookup
= embKernel_get_symbol_list_to_lookup
,
52 SYMBOL_ID_sCurrentTask
= 0,
53 SYMBOL_ID_sListReady
= 1,
54 SYMBOL_ID_sListSleep
= 2,
55 SYMBOL_ID_sListSuspended
= 3,
56 SYMBOL_ID_sMaxPriorities
= 4,
57 SYMBOL_ID_sCurrentTaskCount
= 5,
60 static const char * const embKernel_symbol_list
[] = {
64 "Rtos::sListSuspended",
65 "Rtos::sMaxPriorities",
66 "Rtos::sCurrentTaskCount",
69 struct embKernel_params
{
70 const char *target_name
;
71 const unsigned char pointer_width
;
72 const unsigned char thread_count_width
;
73 const unsigned char rtos_list_size
;
74 const unsigned char thread_stack_offset
;
75 const unsigned char thread_name_offset
;
76 const unsigned char thread_priority_offset
;
77 const unsigned char thread_priority_width
;
78 const unsigned char iterable_next_offset
;
79 const unsigned char iterable_task_owner_offset
;
80 const struct rtos_register_stacking
*stacking_info
;
83 static const struct embKernel_params embKernel_params_list
[] = {
85 "cortex_m", /* target_name */
86 4, /* pointer_width */
87 4, /* thread_count_width */
88 8, /*rtos_list_size */
89 0, /*thread_stack_offset */
90 4, /*thread_name_offset */
91 8, /*thread_priority_offset */
92 4, /*thread_priority_width */
93 4, /*iterable_next_offset */
94 12, /*iterable_task_owner_offset */
95 &rtos_embkernel_Cortex_M_stacking
, /* stacking_info*/
97 { "hla_target", /* target_name */
98 4, /* pointer_width */
99 4, /* thread_count_width */
100 8, /*rtos_list_size */
101 0, /*thread_stack_offset */
102 4, /*thread_name_offset */
103 8, /*thread_priority_offset */
104 4, /*thread_priority_width */
105 4, /*iterable_next_offset */
106 12, /*iterable_task_owner_offset */
107 &rtos_embkernel_Cortex_M_stacking
, /* stacking_info */
111 static bool embKernel_detect_rtos(struct target
*target
)
113 if (target
->rtos
->symbols
!= NULL
) {
114 if (target
->rtos
->symbols
[SYMBOL_ID_sCurrentTask
].address
!= 0)
120 static int embKernel_create(struct target
*target
)
123 while ((i
< ARRAY_SIZE(embKernel_params_list
)) &&
124 (0 != strcmp(embKernel_params_list
[i
].target_name
, target
->type
->name
)))
127 if (i
>= ARRAY_SIZE(embKernel_params_list
)) {
128 LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
129 "list", target
->type
->name
);
133 target
->rtos
->rtos_specific_params
= (void *) &embKernel_params_list
[i
];
137 static int embKernel_get_tasks_details(struct rtos
*rtos
, int64_t iterable
, const struct embKernel_params
*param
,
138 struct thread_detail
*details
, const char* state_str
)
141 int retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_task_owner_offset
, param
->pointer_width
,
143 if (retval
!= ERROR_OK
)
145 details
->threadid
= (threadid_t
) task
;
146 details
->exists
= true;
148 int64_t name_ptr
= 0;
149 retval
= target_read_buffer(rtos
->target
, task
+ param
->thread_name_offset
, param
->pointer_width
,
150 (uint8_t *) &name_ptr
);
151 if (retval
!= ERROR_OK
)
154 details
->thread_name_str
= malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
);
156 retval
= target_read_buffer(rtos
->target
, name_ptr
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
,
157 (uint8_t *) details
->thread_name_str
);
158 if (retval
!= ERROR_OK
)
160 details
->thread_name_str
[EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
- 1] = 0;
162 snprintf(details
->thread_name_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "NoName:[0x%08X]", (unsigned int) task
);
165 int64_t priority
= 0;
166 retval
= target_read_buffer(rtos
->target
, task
+ param
->thread_priority_offset
, param
->thread_priority_width
,
167 (uint8_t *) &priority
);
168 if (retval
!= ERROR_OK
)
170 details
->extra_info_str
= malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
);
171 if (task
== rtos
->current_thread
) {
172 snprintf(details
->extra_info_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "State: Running, Priority: %u",
173 (unsigned int) priority
);
175 snprintf(details
->extra_info_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "State: %s, Priority: %u",
176 state_str
, (unsigned int) priority
);
179 LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable
,
180 (unsigned int)task
, details
->thread_name_str
);
184 static int embKernel_update_threads(struct rtos
*rtos
)
188 const struct embKernel_params
*param
;
193 if (rtos
->rtos_specific_params
== NULL
)
196 if (rtos
->symbols
== NULL
) {
197 LOG_ERROR("No symbols for embKernel");
201 if (rtos
->symbols
[SYMBOL_ID_sCurrentTask
].address
== 0) {
202 LOG_ERROR("Don't have the thread list head");
206 /* wipe out previous thread details if any */
207 rtos_free_threadlist(rtos
);
209 param
= (const struct embKernel_params
*) rtos
->rtos_specific_params
;
211 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sCurrentTask
].address
, param
->pointer_width
,
212 (uint8_t *) &rtos
->current_thread
);
213 if (retval
!= ERROR_OK
) {
214 LOG_ERROR("Error reading current thread in embKernel thread list");
218 int64_t max_used_priority
= 0;
219 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sMaxPriorities
].address
, param
->pointer_width
,
220 (uint8_t *) &max_used_priority
);
221 if (retval
!= ERROR_OK
)
224 int thread_list_size
= 0;
225 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sCurrentTaskCount
].address
,
226 param
->thread_count_width
, (uint8_t *) &thread_list_size
);
228 if (retval
!= ERROR_OK
) {
229 LOG_ERROR("Could not read embKernel thread count from target");
233 /* create space for new thread details */
234 rtos
->thread_details
= malloc(sizeof(struct thread_detail
) * thread_list_size
);
235 if (!rtos
->thread_details
) {
236 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
241 /* Look for ready tasks */
242 for (int pri
= 0; pri
< max_used_priority
; pri
++) {
243 /* Get first item in queue */
244 int64_t iterable
= 0;
245 retval
= target_read_buffer(rtos
->target
,
246 rtos
->symbols
[SYMBOL_ID_sListReady
].address
+ (pri
* param
->rtos_list_size
), param
->pointer_width
,
247 (uint8_t *) &iterable
);
248 if (retval
!= ERROR_OK
)
250 for (; iterable
&& threadIdx
< thread_list_size
; threadIdx
++) {
251 /* Get info from this iterable item */
252 retval
= embKernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[threadIdx
], "Ready");
253 if (retval
!= ERROR_OK
)
255 /* Get next iterable item */
256 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
257 (uint8_t *) &iterable
);
258 if (retval
!= ERROR_OK
)
262 /* Look for sleeping tasks */
263 int64_t iterable
= 0;
264 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sListSleep
].address
, param
->pointer_width
,
265 (uint8_t *) &iterable
);
266 if (retval
!= ERROR_OK
)
268 for (; iterable
&& threadIdx
< thread_list_size
; threadIdx
++) {
269 /*Get info from this iterable item */
270 retval
= embKernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[threadIdx
], "Sleeping");
271 if (retval
!= ERROR_OK
)
273 /*Get next iterable item */
274 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
275 (uint8_t *) &iterable
);
276 if (retval
!= ERROR_OK
)
280 /* Look for suspended tasks */
282 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sListSuspended
].address
, param
->pointer_width
,
283 (uint8_t *) &iterable
);
284 if (retval
!= ERROR_OK
)
286 for (; iterable
&& threadIdx
< thread_list_size
; threadIdx
++) {
287 /* Get info from this iterable item */
288 retval
= embKernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[threadIdx
], "Suspended");
289 if (retval
!= ERROR_OK
)
291 /*Get next iterable item */
292 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
293 (uint8_t *) &iterable
);
294 if (retval
!= ERROR_OK
)
298 rtos
->thread_count
= 0;
299 rtos
->thread_count
= threadIdx
;
300 LOG_OUTPUT("Found %u tasks\n", (unsigned int)threadIdx
);
304 static int embKernel_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
,
305 struct rtos_reg
**reg_list
, int *num_regs
)
308 const struct embKernel_params
*param
;
309 int64_t stack_ptr
= 0;
317 if (rtos
->rtos_specific_params
== NULL
)
320 param
= (const struct embKernel_params
*) rtos
->rtos_specific_params
;
322 /* Read the stack pointer */
323 retval
= target_read_buffer(rtos
->target
, thread_id
+ param
->thread_stack_offset
, param
->pointer_width
,
324 (uint8_t *) &stack_ptr
);
325 if (retval
!= ERROR_OK
) {
326 LOG_ERROR("Error reading stack frame from embKernel thread");
330 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, reg_list
, num_regs
);
333 static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
336 *symbol_list
= calloc(ARRAY_SIZE(embKernel_symbol_list
), sizeof(symbol_table_elem_t
));
338 for (i
= 0; i
< ARRAY_SIZE(embKernel_symbol_list
); i
++)
339 (*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)