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 int 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
, char **hex_reg_list
);
38 static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
40 struct rtos_type embKernel_rtos
= {
42 .detect_rtos
= embKernel_detect_rtos
,
43 .create
= embKernel_create
,
44 .update_threads
= embKernel_update_threads
,
45 .get_thread_reg_list
=
46 embKernel_get_thread_reg_list
,
47 .get_symbol_list_to_lookup
= embKernel_get_symbol_list_to_lookup
,
51 SYMBOL_ID_sCurrentTask
= 0,
52 SYMBOL_ID_sListReady
= 1,
53 SYMBOL_ID_sListSleep
= 2,
54 SYMBOL_ID_sListSuspended
= 3,
55 SYMBOL_ID_sMaxPriorities
= 4,
56 SYMBOL_ID_sCurrentTaskCount
= 5,
59 static const char * const embKernel_symbol_list
[] = {
63 "Rtos::sListSuspended",
64 "Rtos::sMaxPriorities",
65 "Rtos::sCurrentTaskCount",
68 struct embKernel_params
{
69 const char *target_name
;
70 const unsigned char pointer_width
;
71 const unsigned char thread_count_width
;
72 const unsigned char rtos_list_size
;
73 const unsigned char thread_stack_offset
;
74 const unsigned char thread_name_offset
;
75 const unsigned char thread_priority_offset
;
76 const unsigned char thread_priority_width
;
77 const unsigned char iterable_next_offset
;
78 const unsigned char iterable_task_owner_offset
;
79 const struct rtos_register_stacking
*stacking_info
;
82 static const struct embKernel_params embKernel_params_list
[] = {
84 "cortex_m", /* target_name */
85 4, /* pointer_width */
86 4, /* thread_count_width */
87 8, /*rtos_list_size */
88 0, /*thread_stack_offset */
89 4, /*thread_name_offset */
90 8, /*thread_priority_offset */
91 4, /*thread_priority_width */
92 4, /*iterable_next_offset */
93 12, /*iterable_task_owner_offset */
94 &rtos_embkernel_Cortex_M_stacking
, /* stacking_info*/
96 { "hla_target", /* target_name */
97 4, /* pointer_width */
98 4, /* thread_count_width */
99 8, /*rtos_list_size */
100 0, /*thread_stack_offset */
101 4, /*thread_name_offset */
102 8, /*thread_priority_offset */
103 4, /*thread_priority_width */
104 4, /*iterable_next_offset */
105 12, /*iterable_task_owner_offset */
106 &rtos_embkernel_Cortex_M_stacking
, /* stacking_info */
110 static int embKernel_detect_rtos(struct target
*target
)
112 if (target
->rtos
->symbols
!= NULL
) {
113 if (target
->rtos
->symbols
[SYMBOL_ID_sCurrentTask
].address
!= 0)
119 static int embKernel_create(struct target
*target
)
122 while ((i
< ARRAY_SIZE(embKernel_params_list
)) &&
123 (0 != strcmp(embKernel_params_list
[i
].target_name
, target
->type
->name
)))
126 if (i
>= ARRAY_SIZE(embKernel_params_list
)) {
127 LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
128 "list", target
->type
->name
);
132 target
->rtos
->rtos_specific_params
= (void *) &embKernel_params_list
[i
];
136 static int embKernel_get_tasks_details(struct rtos
*rtos
, int64_t iterable
, const struct embKernel_params
*param
,
137 struct thread_detail
*details
, const char* state_str
)
140 int retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_task_owner_offset
, param
->pointer_width
,
142 if (retval
!= ERROR_OK
)
144 details
->threadid
= (threadid_t
) task
;
145 details
->exists
= true;
147 int64_t name_ptr
= 0;
148 retval
= target_read_buffer(rtos
->target
, task
+ param
->thread_name_offset
, param
->pointer_width
,
149 (uint8_t *) &name_ptr
);
150 if (retval
!= ERROR_OK
)
153 details
->thread_name_str
= malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
);
155 retval
= target_read_buffer(rtos
->target
, name_ptr
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
,
156 (uint8_t *) details
->thread_name_str
);
157 if (retval
!= ERROR_OK
)
159 details
->thread_name_str
[EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
- 1] = 0;
161 snprintf(details
->thread_name_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "NoName:[0x%08X]", (unsigned int) task
);
164 int64_t priority
= 0;
165 retval
= target_read_buffer(rtos
->target
, task
+ param
->thread_priority_offset
, param
->thread_priority_width
,
166 (uint8_t *) &priority
);
167 if (retval
!= ERROR_OK
)
169 details
->extra_info_str
= malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
);
170 if (task
== rtos
->current_thread
) {
171 snprintf(details
->extra_info_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "State: Running, Priority: %u",
172 (unsigned int) priority
);
174 snprintf(details
->extra_info_str
, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
, "State: %s, Priority: %u",
175 state_str
, (unsigned int) priority
);
178 LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable
,
179 (unsigned int)task
, details
->thread_name_str
);
183 static int embKernel_update_threads(struct rtos
*rtos
)
187 const struct embKernel_params
*param
;
192 if (rtos
->rtos_specific_params
== NULL
)
195 if (rtos
->symbols
== NULL
) {
196 LOG_ERROR("No symbols for embKernel");
200 if (rtos
->symbols
[SYMBOL_ID_sCurrentTask
].address
== 0) {
201 LOG_ERROR("Don't have the thread list head");
205 /* wipe out previous thread details if any */
206 rtos_free_threadlist(rtos
);
208 param
= (const struct embKernel_params
*) rtos
->rtos_specific_params
;
210 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sCurrentTask
].address
, param
->pointer_width
,
211 (uint8_t *) &rtos
->current_thread
);
212 if (retval
!= ERROR_OK
) {
213 LOG_ERROR("Error reading current thread in embKernel thread list");
217 int64_t max_used_priority
= 0;
218 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sMaxPriorities
].address
, param
->pointer_width
,
219 (uint8_t *) &max_used_priority
);
220 if (retval
!= ERROR_OK
)
223 int thread_list_size
= 0;
224 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sCurrentTaskCount
].address
,
225 param
->thread_count_width
, (uint8_t *) &thread_list_size
);
227 if (retval
!= ERROR_OK
) {
228 LOG_ERROR("Could not read embKernel thread count from target");
232 /* create space for new thread details */
233 rtos
->thread_details
= malloc(sizeof(struct thread_detail
) * thread_list_size
);
234 if (!rtos
->thread_details
) {
235 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
240 /* Look for ready tasks */
241 for (int pri
= 0; pri
< max_used_priority
; pri
++) {
242 /* Get first item in queue */
243 int64_t iterable
= 0;
244 retval
= target_read_buffer(rtos
->target
,
245 rtos
->symbols
[SYMBOL_ID_sListReady
].address
+ (pri
* param
->rtos_list_size
), param
->pointer_width
,
246 (uint8_t *) &iterable
);
247 if (retval
!= ERROR_OK
)
249 for (; iterable
&& threadIdx
< thread_list_size
; threadIdx
++) {
250 /* Get info from this iterable item */
251 retval
= embKernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[threadIdx
], "Ready");
252 if (retval
!= ERROR_OK
)
254 /* Get next iterable item */
255 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
256 (uint8_t *) &iterable
);
257 if (retval
!= ERROR_OK
)
261 /* Look for sleeping tasks */
262 int64_t iterable
= 0;
263 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sListSleep
].address
, param
->pointer_width
,
264 (uint8_t *) &iterable
);
265 if (retval
!= ERROR_OK
)
267 for (; iterable
&& threadIdx
< thread_list_size
; threadIdx
++) {
268 /*Get info from this iterable item */
269 retval
= embKernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[threadIdx
], "Sleeping");
270 if (retval
!= ERROR_OK
)
272 /*Get next iterable item */
273 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
274 (uint8_t *) &iterable
);
275 if (retval
!= ERROR_OK
)
279 /* Look for suspended tasks */
281 retval
= target_read_buffer(rtos
->target
, rtos
->symbols
[SYMBOL_ID_sListSuspended
].address
, param
->pointer_width
,
282 (uint8_t *) &iterable
);
283 if (retval
!= ERROR_OK
)
285 for (; iterable
&& threadIdx
< thread_list_size
; threadIdx
++) {
286 /* Get info from this iterable item */
287 retval
= embKernel_get_tasks_details(rtos
, iterable
, param
, &rtos
->thread_details
[threadIdx
], "Suspended");
288 if (retval
!= ERROR_OK
)
290 /*Get next iterable item */
291 retval
= target_read_buffer(rtos
->target
, iterable
+ param
->iterable_next_offset
, param
->pointer_width
,
292 (uint8_t *) &iterable
);
293 if (retval
!= ERROR_OK
)
297 rtos
->thread_count
= 0;
298 rtos
->thread_count
= threadIdx
;
299 LOG_OUTPUT("Found %u tasks\n", (unsigned int)threadIdx
);
303 static int embKernel_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
306 const struct embKernel_params
*param
;
307 int64_t stack_ptr
= 0;
309 *hex_reg_list
= NULL
;
316 if (rtos
->rtos_specific_params
== NULL
)
319 param
= (const struct embKernel_params
*) rtos
->rtos_specific_params
;
321 /* Read the stack pointer */
322 retval
= target_read_buffer(rtos
->target
, thread_id
+ param
->thread_stack_offset
, param
->pointer_width
,
323 (uint8_t *) &stack_ptr
);
324 if (retval
!= ERROR_OK
) {
325 LOG_ERROR("Error reading stack frame from embKernel thread");
329 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
332 static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
335 *symbol_list
= calloc(ARRAY_SIZE(embKernel_symbol_list
), sizeof(symbol_table_elem_t
));
337 for (i
= 0; i
< ARRAY_SIZE(embKernel_symbol_list
); i
++)
338 (*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)