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 struct eCos_thread_state eCos_thread_states
[] = {
52 #define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state))
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 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 char *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 if (rtos
->thread_details
!= NULL
) {
130 for (j
= 0; j
< rtos
->thread_count
; j
++) {
131 if (rtos
->thread_details
[j
].display_str
!= NULL
) {
132 free(rtos
->thread_details
[j
].display_str
);
133 rtos
->thread_details
[j
].display_str
= NULL
;
135 if (rtos
->thread_details
[j
].thread_name_str
!= NULL
) {
136 free(rtos
->thread_details
[j
].thread_name_str
);
137 rtos
->thread_details
[j
].thread_name_str
= NULL
;
139 if (rtos
->thread_details
[j
].extra_info_str
!= NULL
) {
140 free(rtos
->thread_details
[j
].extra_info_str
);
141 rtos
->thread_details
[j
].extra_info_str
= NULL
;
144 free(rtos
->thread_details
);
145 rtos
->thread_details
= NULL
;
148 /* determine the number of current threads */
149 uint32_t thread_list_head
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
150 uint32_t thread_index
;
151 target_read_buffer(rtos
->target
,
153 param
->pointer_width
,
154 (uint8_t *) &thread_index
);
155 uint32_t first_thread
= thread_index
;
158 retval
= target_read_buffer(rtos
->target
,
159 thread_index
+ param
->thread_next_offset
,
160 param
->pointer_width
,
161 (uint8_t *) &thread_index
);
162 if (retval
!= ERROR_OK
)
164 } while (thread_index
!= first_thread
);
166 /* read the current thread id */
167 uint32_t current_thread_addr
;
168 retval
= target_read_buffer(rtos
->target
,
169 rtos
->symbols
[eCos_VAL_current_thread_ptr
].address
,
171 (uint8_t *)¤t_thread_addr
);
172 if (retval
!= ERROR_OK
)
174 rtos
->current_thread
= 0;
175 retval
= target_read_buffer(rtos
->target
,
176 current_thread_addr
+ param
->thread_uniqueid_offset
,
178 (uint8_t *)&rtos
->current_thread
);
179 if (retval
!= ERROR_OK
) {
180 LOG_ERROR("Could not read eCos current thread from target");
184 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
185 /* Either : No RTOS threads - there is always at least the current execution though */
186 /* OR : No current thread - all threads suspended - show the current execution
188 char tmp_str
[] = "Current Execution";
191 rtos
->thread_details
= (struct thread_detail
*) malloc(
192 sizeof(struct thread_detail
) * thread_list_size
);
193 rtos
->thread_details
->threadid
= 1;
194 rtos
->thread_details
->exists
= true;
195 rtos
->thread_details
->display_str
= NULL
;
196 rtos
->thread_details
->extra_info_str
= NULL
;
197 rtos
->thread_details
->thread_name_str
= (char *) malloc(sizeof(tmp_str
));
198 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
200 if (thread_list_size
== 0) {
201 rtos
->thread_count
= 1;
205 /* create space for new thread details */
206 rtos
->thread_details
= (struct thread_detail
*) malloc(
207 sizeof(struct thread_detail
) * thread_list_size
);
210 /* loop over all threads */
211 thread_index
= first_thread
;
214 #define ECOS_THREAD_NAME_STR_SIZE (200)
215 char tmp_str
[ECOS_THREAD_NAME_STR_SIZE
];
217 uint32_t name_ptr
= 0;
218 uint32_t prev_thread_ptr
;
220 /* Save the thread pointer */
222 retval
= target_read_buffer(rtos
->target
,
223 thread_index
+ param
->thread_uniqueid_offset
,
225 (uint8_t *)&thread_id
);
226 if (retval
!= ERROR_OK
) {
227 LOG_ERROR("Could not read eCos thread id from target");
230 rtos
->thread_details
[tasks_found
].threadid
= thread_id
;
232 /* read the name pointer */
233 retval
= target_read_buffer(rtos
->target
,
234 thread_index
+ param
->thread_name_offset
,
235 param
->pointer_width
,
236 (uint8_t *)&name_ptr
);
237 if (retval
!= ERROR_OK
) {
238 LOG_ERROR("Could not read eCos thread name pointer from target");
242 /* Read the thread name */
244 target_read_buffer(rtos
->target
,
246 ECOS_THREAD_NAME_STR_SIZE
,
247 (uint8_t *)&tmp_str
);
248 if (retval
!= ERROR_OK
) {
249 LOG_ERROR("Error reading thread name from eCos target");
252 tmp_str
[ECOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
254 if (tmp_str
[0] == '\x00')
255 strcpy(tmp_str
, "No Name");
257 rtos
->thread_details
[tasks_found
].thread_name_str
=
258 (char *)malloc(strlen(tmp_str
)+1);
259 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
261 /* Read the thread status */
262 int64_t thread_status
= 0;
263 retval
= target_read_buffer(rtos
->target
,
264 thread_index
+ param
->thread_state_offset
,
266 (uint8_t *)&thread_status
);
267 if (retval
!= ERROR_OK
) {
268 LOG_ERROR("Error reading thread state from eCos target");
272 for (i
= 0; (i
< ECOS_NUM_STATES
) && (eCos_thread_states
[i
].value
!= thread_status
); i
++) {
279 if (i
< ECOS_NUM_STATES
)
280 state_desc
= eCos_thread_states
[i
].desc
;
282 state_desc
= "Unknown state";
284 rtos
->thread_details
[tasks_found
].extra_info_str
= (char *)malloc(strlen(
286 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
, state_desc
);
288 rtos
->thread_details
[tasks_found
].exists
= true;
290 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
293 prev_thread_ptr
= thread_index
;
295 /* Get the location of the next thread structure. */
296 thread_index
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
297 retval
= target_read_buffer(rtos
->target
,
298 prev_thread_ptr
+ param
->thread_next_offset
,
299 param
->pointer_width
,
300 (uint8_t *) &thread_index
);
301 if (retval
!= ERROR_OK
) {
302 LOG_ERROR("Error reading next thread pointer in eCos thread list");
305 } while (thread_index
!= first_thread
);
307 rtos
->thread_count
= tasks_found
;
311 static int eCos_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
314 const struct eCos_params
*param
;
316 *hex_reg_list
= NULL
;
324 if (rtos
->rtos_specific_params
== NULL
)
327 param
= (const struct eCos_params
*) rtos
->rtos_specific_params
;
329 /* Find the thread with that thread id */
331 uint32_t thread_list_head
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
332 uint32_t thread_index
;
333 target_read_buffer(rtos
->target
, thread_list_head
, param
->pointer_width
,
334 (uint8_t *)&thread_index
);
337 retval
= target_read_buffer(rtos
->target
,
338 thread_index
+ param
->thread_uniqueid_offset
,
341 if (retval
!= ERROR_OK
) {
342 LOG_ERROR("Error reading unique id from eCos thread");
346 if (id
== thread_id
) {
350 target_read_buffer(rtos
->target
,
351 thread_index
+ param
->thread_next_offset
,
352 param
->pointer_width
,
353 (uint8_t *) &thread_index
);
357 /* Read the stack pointer */
358 int64_t stack_ptr
= 0;
359 retval
= target_read_buffer(rtos
->target
,
360 thread_index
+ param
->thread_stack_offset
,
361 param
->pointer_width
,
362 (uint8_t *)&stack_ptr
);
363 if (retval
!= ERROR_OK
) {
364 LOG_ERROR("Error reading stack frame from eCos thread");
368 return rtos_generic_stack_read(rtos
->target
,
369 param
->stacking_info
,
377 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
380 *symbol_list
= (symbol_table_elem_t
*) malloc(
381 sizeof(symbol_table_elem_t
) * ARRAY_SIZE(eCos_symbol_list
));
383 for (i
= 0; i
< ARRAY_SIZE(eCos_symbol_list
); i
++)
384 (*symbol_list
)[i
].symbol_name
= eCos_symbol_list
[i
];
389 static int eCos_detect_rtos(struct target
*target
)
391 if ((target
->rtos
->symbols
!= NULL
) &&
392 (target
->rtos
->symbols
[eCos_VAL_thread_list
].address
!= 0)) {
393 /* looks like eCos */
399 static int eCos_create(struct target
*target
)
402 while ((i
< ECOS_NUM_PARAMS
) &&
403 (0 != strcmp(eCos_params_list
[i
].target_name
, target
->type
->name
))) {
406 if (i
>= ECOS_NUM_PARAMS
) {
407 LOG_ERROR("Could not find target in eCos compatibility list");
411 target
->rtos
->rtos_specific_params
= (void *) &eCos_params_list
[i
];
412 target
->rtos
->current_thread
= 0;
413 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)