1 /***************************************************************************
3 * This program is free software; you can redistribute it and/or modify *
4 * it under the terms of the GNU General Public License as published by *
5 * the Free Software Foundation; either version 2 of the License, or *
6 * (at your option) any later version. *
8 * This program is distributed in the hope that it will be useful, *
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
11 * GNU General Public License for more details. *
13 * You should have received a copy of the GNU General Public License *
14 * along with this program; if not, write to the *
15 * Free Software Foundation, Inc., *
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
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_ecos_stackings.h"
32 static int eCos_detect_rtos(struct target
*target
);
33 static int eCos_create(struct target
*target
);
34 static int eCos_update_threads(struct rtos
*rtos
);
35 static int eCos_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
);
36 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
38 struct eCos_thread_state
{
43 static const struct eCos_thread_state eCos_thread_states
[] = {
52 #define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state))
55 const char *target_name
;
56 unsigned char pointer_width
;
57 unsigned char thread_stack_offset
;
58 unsigned char thread_name_offset
;
59 unsigned char thread_state_offset
;
60 unsigned char thread_next_offset
;
61 unsigned char thread_uniqueid_offset
;
62 const struct rtos_register_stacking
*stacking_info
;
65 static const struct eCos_params eCos_params_list
[] = {
67 "cortex_m", /* target_name */
68 4, /* pointer_width; */
69 0x0c, /* thread_stack_offset; */
70 0x9c, /* thread_name_offset; */
71 0x3c, /* thread_state_offset; */
72 0xa0, /* thread_next_offset */
73 0x4c, /* thread_uniqueid_offset */
74 &rtos_eCos_Cortex_M3_stacking
/* stacking_info */
78 #define ECOS_NUM_PARAMS ((int)(sizeof(eCos_params_list)/sizeof(struct eCos_params)))
80 enum eCos_symbol_values
{
81 eCos_VAL_thread_list
= 0,
82 eCos_VAL_current_thread_ptr
= 1
85 static const char * const eCos_symbol_list
[] = {
86 "Cyg_Thread::thread_list",
87 "Cyg_Scheduler_Base::current_thread",
91 const struct rtos_type eCos_rtos
= {
94 .detect_rtos
= eCos_detect_rtos
,
95 .create
= eCos_create
,
96 .update_threads
= eCos_update_threads
,
97 .get_thread_reg_list
= eCos_get_thread_reg_list
,
98 .get_symbol_list_to_lookup
= eCos_get_symbol_list_to_lookup
,
102 static int eCos_update_threads(struct rtos
*rtos
)
106 int thread_list_size
= 0;
107 const struct eCos_params
*param
;
112 if (rtos
->rtos_specific_params
== NULL
)
115 param
= (const struct eCos_params
*) rtos
->rtos_specific_params
;
117 if (rtos
->symbols
== NULL
) {
118 LOG_ERROR("No symbols for eCos");
122 if (rtos
->symbols
[eCos_VAL_thread_list
].address
== 0) {
123 LOG_ERROR("Don't have the thread list head");
127 /* wipe out previous thread details if any */
128 rtos_free_threadlist(rtos
);
130 /* determine the number of current threads */
131 uint32_t thread_list_head
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
132 uint32_t thread_index
;
133 target_read_buffer(rtos
->target
,
135 param
->pointer_width
,
136 (uint8_t *) &thread_index
);
137 uint32_t first_thread
= thread_index
;
140 retval
= target_read_buffer(rtos
->target
,
141 thread_index
+ param
->thread_next_offset
,
142 param
->pointer_width
,
143 (uint8_t *) &thread_index
);
144 if (retval
!= ERROR_OK
)
146 } while (thread_index
!= first_thread
);
148 /* read the current thread id */
149 uint32_t current_thread_addr
;
150 retval
= target_read_buffer(rtos
->target
,
151 rtos
->symbols
[eCos_VAL_current_thread_ptr
].address
,
153 (uint8_t *)¤t_thread_addr
);
154 if (retval
!= ERROR_OK
)
156 rtos
->current_thread
= 0;
157 retval
= target_read_buffer(rtos
->target
,
158 current_thread_addr
+ param
->thread_uniqueid_offset
,
160 (uint8_t *)&rtos
->current_thread
);
161 if (retval
!= ERROR_OK
) {
162 LOG_ERROR("Could not read eCos current thread from target");
166 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
167 /* Either : No RTOS threads - there is always at least the current execution though */
168 /* OR : No current thread - all threads suspended - show the current execution
170 char tmp_str
[] = "Current Execution";
173 rtos
->thread_details
= malloc(
174 sizeof(struct thread_detail
) * thread_list_size
);
175 rtos
->thread_details
->threadid
= 1;
176 rtos
->thread_details
->exists
= true;
177 rtos
->thread_details
->display_str
= NULL
;
178 rtos
->thread_details
->extra_info_str
= NULL
;
179 rtos
->thread_details
->thread_name_str
= malloc(sizeof(tmp_str
));
180 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
182 if (thread_list_size
== 0) {
183 rtos
->thread_count
= 1;
187 /* create space for new thread details */
188 rtos
->thread_details
= malloc(
189 sizeof(struct thread_detail
) * thread_list_size
);
192 /* loop over all threads */
193 thread_index
= first_thread
;
196 #define ECOS_THREAD_NAME_STR_SIZE (200)
197 char tmp_str
[ECOS_THREAD_NAME_STR_SIZE
];
199 uint32_t name_ptr
= 0;
200 uint32_t prev_thread_ptr
;
202 /* Save the thread pointer */
204 retval
= target_read_buffer(rtos
->target
,
205 thread_index
+ param
->thread_uniqueid_offset
,
207 (uint8_t *)&thread_id
);
208 if (retval
!= ERROR_OK
) {
209 LOG_ERROR("Could not read eCos thread id from target");
212 rtos
->thread_details
[tasks_found
].threadid
= thread_id
;
214 /* read the name pointer */
215 retval
= target_read_buffer(rtos
->target
,
216 thread_index
+ param
->thread_name_offset
,
217 param
->pointer_width
,
218 (uint8_t *)&name_ptr
);
219 if (retval
!= ERROR_OK
) {
220 LOG_ERROR("Could not read eCos thread name pointer from target");
224 /* Read the thread name */
226 target_read_buffer(rtos
->target
,
228 ECOS_THREAD_NAME_STR_SIZE
,
229 (uint8_t *)&tmp_str
);
230 if (retval
!= ERROR_OK
) {
231 LOG_ERROR("Error reading thread name from eCos target");
234 tmp_str
[ECOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
236 if (tmp_str
[0] == '\x00')
237 strcpy(tmp_str
, "No Name");
239 rtos
->thread_details
[tasks_found
].thread_name_str
=
240 malloc(strlen(tmp_str
)+1);
241 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
243 /* Read the thread status */
244 int64_t thread_status
= 0;
245 retval
= target_read_buffer(rtos
->target
,
246 thread_index
+ param
->thread_state_offset
,
248 (uint8_t *)&thread_status
);
249 if (retval
!= ERROR_OK
) {
250 LOG_ERROR("Error reading thread state from eCos target");
254 for (i
= 0; (i
< ECOS_NUM_STATES
) && (eCos_thread_states
[i
].value
!= thread_status
); i
++) {
260 const char *state_desc
;
261 if (i
< ECOS_NUM_STATES
)
262 state_desc
= eCos_thread_states
[i
].desc
;
264 state_desc
= "Unknown state";
266 rtos
->thread_details
[tasks_found
].extra_info_str
= malloc(strlen(
268 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
, state_desc
);
270 rtos
->thread_details
[tasks_found
].exists
= true;
272 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
275 prev_thread_ptr
= thread_index
;
277 /* Get the location of the next thread structure. */
278 thread_index
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
279 retval
= target_read_buffer(rtos
->target
,
280 prev_thread_ptr
+ param
->thread_next_offset
,
281 param
->pointer_width
,
282 (uint8_t *) &thread_index
);
283 if (retval
!= ERROR_OK
) {
284 LOG_ERROR("Error reading next thread pointer in eCos thread list");
287 } while (thread_index
!= first_thread
);
289 rtos
->thread_count
= tasks_found
;
293 static int eCos_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
296 const struct eCos_params
*param
;
298 *hex_reg_list
= NULL
;
306 if (rtos
->rtos_specific_params
== NULL
)
309 param
= (const struct eCos_params
*) rtos
->rtos_specific_params
;
311 /* Find the thread with that thread id */
313 uint32_t thread_list_head
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
314 uint32_t thread_index
;
315 target_read_buffer(rtos
->target
, thread_list_head
, param
->pointer_width
,
316 (uint8_t *)&thread_index
);
319 retval
= target_read_buffer(rtos
->target
,
320 thread_index
+ param
->thread_uniqueid_offset
,
323 if (retval
!= ERROR_OK
) {
324 LOG_ERROR("Error reading unique id from eCos thread");
328 if (id
== thread_id
) {
332 target_read_buffer(rtos
->target
,
333 thread_index
+ param
->thread_next_offset
,
334 param
->pointer_width
,
335 (uint8_t *) &thread_index
);
339 /* Read the stack pointer */
340 int64_t stack_ptr
= 0;
341 retval
= target_read_buffer(rtos
->target
,
342 thread_index
+ param
->thread_stack_offset
,
343 param
->pointer_width
,
344 (uint8_t *)&stack_ptr
);
345 if (retval
!= ERROR_OK
) {
346 LOG_ERROR("Error reading stack frame from eCos thread");
350 return rtos_generic_stack_read(rtos
->target
,
351 param
->stacking_info
,
359 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
362 *symbol_list
= malloc(
363 sizeof(symbol_table_elem_t
) * ARRAY_SIZE(eCos_symbol_list
));
365 for (i
= 0; i
< ARRAY_SIZE(eCos_symbol_list
); i
++)
366 (*symbol_list
)[i
].symbol_name
= eCos_symbol_list
[i
];
371 static int eCos_detect_rtos(struct target
*target
)
373 if ((target
->rtos
->symbols
!= NULL
) &&
374 (target
->rtos
->symbols
[eCos_VAL_thread_list
].address
!= 0)) {
375 /* looks like eCos */
381 static int eCos_create(struct target
*target
)
384 while ((i
< ECOS_NUM_PARAMS
) &&
385 (0 != strcmp(eCos_params_list
[i
].target_name
, target
->type
->name
))) {
388 if (i
>= ECOS_NUM_PARAMS
) {
389 LOG_ERROR("Could not find target in eCos compatibility list");
393 target
->rtos
->rtos_specific_params
= (void *) &eCos_params_list
[i
];
394 target
->rtos
->current_thread
= 0;
395 target
->rtos
->thread_details
= NULL
;
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)