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_embkernel_stackings.h"
34 #define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64)
36 static int embKernel_detect_rtos(struct target
*target
);
37 static int embKernel_create(struct target
*target
);
38 static int embKernel_update_threads(struct rtos
*rtos
);
39 static int embKernel_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
);
40 static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
42 struct rtos_type embKernel_rtos
= {
44 .detect_rtos
= embKernel_detect_rtos
,
45 .create
= embKernel_create
,
46 .update_threads
= embKernel_update_threads
,
47 .get_thread_reg_list
=
48 embKernel_get_thread_reg_list
,
49 .get_symbol_list_to_lookup
= embKernel_get_symbol_list_to_lookup
,
53 SYMBOL_ID_sCurrentTask
= 0,
54 SYMBOL_ID_sListReady
= 1,
55 SYMBOL_ID_sListSleep
= 2,
56 SYMBOL_ID_sListSuspended
= 3,
57 SYMBOL_ID_sMaxPriorities
= 4,
58 SYMBOL_ID_sCurrentTaskCount
= 5,
61 static char *embKernel_symbol_list
[] = {
65 "Rtos::sListSuspended",
66 "Rtos::sMaxPriorities",
67 "Rtos::sCurrentTaskCount",
70 struct embKernel_params
{
71 const char *target_name
;
72 const unsigned char pointer_width
;
73 const unsigned char thread_count_width
;
74 const unsigned char rtos_list_size
;
75 const unsigned char thread_stack_offset
;
76 const unsigned char thread_name_offset
;
77 const unsigned char thread_priority_offset
;
78 const unsigned char thread_priority_width
;
79 const unsigned char iterable_next_offset
;
80 const unsigned char iterable_task_owner_offset
;
81 const struct rtos_register_stacking
*stacking_info
;
84 struct embKernel_params embKernel_params_list
[] = {
86 "cortex_m3", /* 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_M3_stacking
, /* stacking_info*/
98 { "hla_target", /* target_name */
99 4, /* pointer_width */
100 4, /* thread_count_width */
101 8, /*rtos_list_size */
102 0, /*thread_stack_offset */
103 4, /*thread_name_offset */
104 8, /*thread_priority_offset */
105 4, /*thread_priority_width */
106 4, /*iterable_next_offset */
107 12, /*iterable_task_owner_offset */
108 &rtos_embkernel_Cortex_M3_stacking
, /* stacking_info */
112 static int embKernel_detect_rtos(struct target
*target
)
114 if (target
->rtos
->symbols
!= NULL
) {
115 if (target
->rtos
->symbols
[SYMBOL_ID_sCurrentTask
].address
!= 0)
121 static int embKernel_create(struct target
*target
)
124 while ((i
< ARRAY_SIZE(embKernel_params_list
)) &&
125 (0 != strcmp(embKernel_params_list
[i
].target_name
, target
->type
->name
)))
128 if (i
>= ARRAY_SIZE(embKernel_params_list
)) {
129 LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
130 "list", target
->type
->name
);
134 target
->rtos
->rtos_specific_params
= (void *) &embKernel_params_list
[i
];
138 static int embKernel_get_tasks_details(struct rtos
*rtos
, int64_t iterable
, const struct embKernel_params
*param
,
139 struct thread_detail
*details
, const char* state_str
)
142 int retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_task_owner_offset
, param
->pointer_width
,
144 if (retval
!= ERROR_OK
)
146 details
->threadid
= (threadid_t
) task
;
147 details
->exists
= true;
148 details
->display_str
= NULL
;
150 int64_t name_ptr
= 0;
151 retval
= target_read_buffer(rtos
->target
, task
+ param
->thread_name_offset
, param
->pointer_width
,
152 (uint8_t *) &name_ptr
);
153 if (retval
!= ERROR_OK
)
156 details
->thread_name_str
= malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
);
158 retval
= target_read_buffer(rtos
->target
, name_ptr
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
,
159 (uint8_t *) details
->thread_name_str
);
160 if (retval
!= ERROR_OK
)
162 details
->thread_name_str
[EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
- 1] = 0;
164 snprintf(details
->thread_name_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "NoName:[0x%08X]", (unsigned int) task
);
167 int64_t priority
= 0;
168 retval
= target_read_buffer(rtos
->target
, task
+ param
->thread_priority_offset
, param
->thread_priority_width
,
169 (uint8_t *) &priority
);
170 if (retval
!= ERROR_OK
)
172 details
->extra_info_str
= (char *) malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
);
173 if (task
== rtos
->current_thread
) {
174 snprintf(details
->extra_info_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "Pri=%u, Running",
175 (unsigned int) priority
);
177 snprintf(details
->extra_info_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "Pri=%u, %s", (unsigned int) priority
,
181 LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable
,
182 (unsigned int)task
, details
->thread_name_str
);
186 static int embKernel_update_threads(struct rtos
*rtos
)
190 const struct embKernel_params
*param
;
195 if (rtos
->rtos_specific_params
== NULL
)
198 if (rtos
->symbols
== NULL
) {
199 LOG_ERROR("No symbols for embKernel");
203 if (rtos
->symbols
[SYMBOL_ID_sCurrentTask
].address
== 0) {
204 LOG_ERROR("Don't have the thread list head");
208 /* wipe out previous thread details if any */
209 if (rtos
->thread_details
!= NULL
) {
211 for (j
= 0; j
< rtos
->thread_count
; j
++) {
212 if (rtos
->thread_details
[j
].display_str
!= NULL
) {
213 free(rtos
->thread_details
[j
].display_str
);
214 rtos
->thread_details
[j
].display_str
= NULL
;
216 if (rtos
->thread_details
[j
].thread_name_str
!= NULL
) {
217 free(rtos
->thread_details
[j
].thread_name_str
);
218 rtos
->thread_details
[j
].thread_name_str
= NULL
;
220 if (rtos
->thread_details
[j
].extra_info_str
!= NULL
) {
221 free(rtos
->thread_details
[j
].extra_info_str
);
222 rtos
->thread_details
[j
].extra_info_str
= NULL
;
225 free(rtos
->thread_details
);
226 rtos
->thread_details
= NULL
;
229 param
= (const struct embKernel_params
*) rtos
->rtos_specific_params
;
231 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sCurrentTask
].address
, param
->pointer_width
,
232 (uint8_t *) &rtos
->current_thread
);
233 if (retval
!= ERROR_OK
) {
234 LOG_ERROR("Error reading current thread in embKernel thread list");
238 int64_t max_used_priority
= 0;
239 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sMaxPriorities
].address
, param
->pointer_width
,
240 (uint8_t *) &max_used_priority
);
241 if (retval
!= ERROR_OK
)
244 int thread_list_size
= 0;
245 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sCurrentTaskCount
].address
,
246 param
->thread_count_width
, (uint8_t *) &thread_list_size
);
248 if (retval
!= ERROR_OK
) {
249 LOG_ERROR("Could not read embKernel thread count from target");
253 /* create space for new thread details */
254 rtos
->thread_details
= (struct thread_detail
*) malloc(sizeof(struct thread_detail
) * thread_list_size
);
255 if (!rtos
->thread_details
) {
256 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
261 /* Look for ready tasks */
262 for (int pri
= 0; pri
< max_used_priority
; pri
++) {
263 /* Get first item in queue */
264 int64_t iterable
= 0;
265 retval
= target_read_buffer(rtos
->target
,
266 rtos
->symbols
[SYMBOL_ID_sListReady
].address
+ (pri
* param
->rtos_list_size
), param
->pointer_width
,
267 (uint8_t *) &iterable
);
268 if (retval
!= ERROR_OK
)
270 for (; iterable
&& threadIdx
< thread_list_size
; threadIdx
++) {
271 /* Get info from this iterable item */
272 retval
= embKernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[threadIdx
], "Ready");
273 if (retval
!= ERROR_OK
)
275 /* Get next iterable item */
276 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
277 (uint8_t *) &iterable
);
278 if (retval
!= ERROR_OK
)
282 /* Look for sleeping tasks */
283 int64_t iterable
= 0;
284 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sListSleep
].address
, param
->pointer_width
,
285 (uint8_t *) &iterable
);
286 if (retval
!= ERROR_OK
)
288 for (; iterable
&& threadIdx
< thread_list_size
; threadIdx
++) {
289 /*Get info from this iterable item */
290 retval
= embKernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[threadIdx
], "Sleeping");
291 if (retval
!= ERROR_OK
)
293 /*Get next iterable item */
294 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
295 (uint8_t *) &iterable
);
296 if (retval
!= ERROR_OK
)
300 /* Look for suspended tasks */
302 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sListSuspended
].address
, param
->pointer_width
,
303 (uint8_t *) &iterable
);
304 if (retval
!= ERROR_OK
)
306 for (; iterable
&& threadIdx
< thread_list_size
; threadIdx
++) {
307 /* Get info from this iterable item */
308 retval
= embKernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[threadIdx
], "Suspended");
309 if (retval
!= ERROR_OK
)
311 /*Get next iterable item */
312 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
313 (uint8_t *) &iterable
);
314 if (retval
!= ERROR_OK
)
318 rtos
->thread_count
= 0;
319 rtos
->thread_count
= threadIdx
;
320 LOG_OUTPUT("Found %u tasks\n", (unsigned int)threadIdx
);
324 static int embKernel_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
327 const struct embKernel_params
*param
;
328 int64_t stack_ptr
= 0;
330 *hex_reg_list
= NULL
;
337 if (rtos
->rtos_specific_params
== NULL
)
340 param
= (const struct embKernel_params
*) rtos
->rtos_specific_params
;
342 /* Read the stack pointer */
343 retval
= target_read_buffer(rtos
->target
, thread_id
+ param
->thread_stack_offset
, param
->pointer_width
,
344 (uint8_t *) &stack_ptr
);
345 if (retval
!= ERROR_OK
) {
346 LOG_ERROR("Error reading stack frame from embKernel thread");
350 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
353 static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
356 *symbol_list
= (symbol_table_elem_t
*) malloc(sizeof(symbol_table_elem_t
) * ARRAY_SIZE(embKernel_symbol_list
));
358 for (i
= 0; i
< ARRAY_SIZE(embKernel_symbol_list
); i
++)
359 (*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)