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, see <http://www.gnu.org/licenses/>. *
15 ***************************************************************************/
21 #include <helper/time_support.h>
22 #include <jtag/jtag.h>
23 #include "target/target.h"
24 #include "target/target_type.h"
26 #include "helper/log.h"
27 #include "helper/types.h"
28 #include "rtos_ecos_stackings.h"
30 static int eCos_detect_rtos(struct target
*target
);
31 static int eCos_create(struct target
*target
);
32 static int eCos_update_threads(struct rtos
*rtos
);
33 static int eCos_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
);
34 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
36 struct eCos_thread_state
{
41 static const struct eCos_thread_state eCos_thread_states
[] = {
50 #define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state))
53 const char *target_name
;
54 unsigned char pointer_width
;
55 unsigned char thread_stack_offset
;
56 unsigned char thread_name_offset
;
57 unsigned char thread_state_offset
;
58 unsigned char thread_next_offset
;
59 unsigned char thread_uniqueid_offset
;
60 const struct rtos_register_stacking
*stacking_info
;
63 static const struct eCos_params eCos_params_list
[] = {
65 "cortex_m", /* target_name */
66 4, /* pointer_width; */
67 0x0c, /* thread_stack_offset; */
68 0x9c, /* thread_name_offset; */
69 0x3c, /* thread_state_offset; */
70 0xa0, /* thread_next_offset */
71 0x4c, /* thread_uniqueid_offset */
72 &rtos_eCos_Cortex_M3_stacking
/* stacking_info */
76 #define ECOS_NUM_PARAMS ((int)(sizeof(eCos_params_list)/sizeof(struct eCos_params)))
78 enum eCos_symbol_values
{
79 eCos_VAL_thread_list
= 0,
80 eCos_VAL_current_thread_ptr
= 1
83 static const char * const eCos_symbol_list
[] = {
84 "Cyg_Thread::thread_list",
85 "Cyg_Scheduler_Base::current_thread",
89 const struct rtos_type eCos_rtos
= {
92 .detect_rtos
= eCos_detect_rtos
,
93 .create
= eCos_create
,
94 .update_threads
= eCos_update_threads
,
95 .get_thread_reg_list
= eCos_get_thread_reg_list
,
96 .get_symbol_list_to_lookup
= eCos_get_symbol_list_to_lookup
,
100 static int eCos_update_threads(struct rtos
*rtos
)
104 int thread_list_size
= 0;
105 const struct eCos_params
*param
;
110 if (rtos
->rtos_specific_params
== NULL
)
113 param
= (const struct eCos_params
*) rtos
->rtos_specific_params
;
115 if (rtos
->symbols
== NULL
) {
116 LOG_ERROR("No symbols for eCos");
120 if (rtos
->symbols
[eCos_VAL_thread_list
].address
== 0) {
121 LOG_ERROR("Don't have the thread list head");
125 /* wipe out previous thread details if any */
126 rtos_free_threadlist(rtos
);
128 /* determine the number of current threads */
129 uint32_t thread_list_head
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
130 uint32_t thread_index
;
131 target_read_buffer(rtos
->target
,
133 param
->pointer_width
,
134 (uint8_t *) &thread_index
);
135 uint32_t first_thread
= thread_index
;
138 retval
= target_read_buffer(rtos
->target
,
139 thread_index
+ param
->thread_next_offset
,
140 param
->pointer_width
,
141 (uint8_t *) &thread_index
);
142 if (retval
!= ERROR_OK
)
144 } while (thread_index
!= first_thread
);
146 /* read the current thread id */
147 uint32_t current_thread_addr
;
148 retval
= target_read_buffer(rtos
->target
,
149 rtos
->symbols
[eCos_VAL_current_thread_ptr
].address
,
151 (uint8_t *)¤t_thread_addr
);
152 if (retval
!= ERROR_OK
)
154 rtos
->current_thread
= 0;
155 retval
= target_read_buffer(rtos
->target
,
156 current_thread_addr
+ param
->thread_uniqueid_offset
,
158 (uint8_t *)&rtos
->current_thread
);
159 if (retval
!= ERROR_OK
) {
160 LOG_ERROR("Could not read eCos current thread from target");
164 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
165 /* Either : No RTOS threads - there is always at least the current execution though */
166 /* OR : No current thread - all threads suspended - show the current execution
168 char tmp_str
[] = "Current Execution";
171 rtos
->thread_details
= malloc(
172 sizeof(struct thread_detail
) * thread_list_size
);
173 rtos
->thread_details
->threadid
= 1;
174 rtos
->thread_details
->exists
= true;
175 rtos
->thread_details
->display_str
= NULL
;
176 rtos
->thread_details
->extra_info_str
= NULL
;
177 rtos
->thread_details
->thread_name_str
= malloc(sizeof(tmp_str
));
178 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
180 if (thread_list_size
== 0) {
181 rtos
->thread_count
= 1;
185 /* create space for new thread details */
186 rtos
->thread_details
= malloc(
187 sizeof(struct thread_detail
) * thread_list_size
);
190 /* loop over all threads */
191 thread_index
= first_thread
;
194 #define ECOS_THREAD_NAME_STR_SIZE (200)
195 char tmp_str
[ECOS_THREAD_NAME_STR_SIZE
];
197 uint32_t name_ptr
= 0;
198 uint32_t prev_thread_ptr
;
200 /* Save the thread pointer */
202 retval
= target_read_buffer(rtos
->target
,
203 thread_index
+ param
->thread_uniqueid_offset
,
205 (uint8_t *)&thread_id
);
206 if (retval
!= ERROR_OK
) {
207 LOG_ERROR("Could not read eCos thread id from target");
210 rtos
->thread_details
[tasks_found
].threadid
= thread_id
;
212 /* read the name pointer */
213 retval
= target_read_buffer(rtos
->target
,
214 thread_index
+ param
->thread_name_offset
,
215 param
->pointer_width
,
216 (uint8_t *)&name_ptr
);
217 if (retval
!= ERROR_OK
) {
218 LOG_ERROR("Could not read eCos thread name pointer from target");
222 /* Read the thread name */
224 target_read_buffer(rtos
->target
,
226 ECOS_THREAD_NAME_STR_SIZE
,
227 (uint8_t *)&tmp_str
);
228 if (retval
!= ERROR_OK
) {
229 LOG_ERROR("Error reading thread name from eCos target");
232 tmp_str
[ECOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
234 if (tmp_str
[0] == '\x00')
235 strcpy(tmp_str
, "No Name");
237 rtos
->thread_details
[tasks_found
].thread_name_str
=
238 malloc(strlen(tmp_str
)+1);
239 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
241 /* Read the thread status */
242 int64_t thread_status
= 0;
243 retval
= target_read_buffer(rtos
->target
,
244 thread_index
+ param
->thread_state_offset
,
246 (uint8_t *)&thread_status
);
247 if (retval
!= ERROR_OK
) {
248 LOG_ERROR("Error reading thread state from eCos target");
252 for (i
= 0; (i
< ECOS_NUM_STATES
) && (eCos_thread_states
[i
].value
!= thread_status
); i
++) {
258 const char *state_desc
;
259 if (i
< ECOS_NUM_STATES
)
260 state_desc
= eCos_thread_states
[i
].desc
;
262 state_desc
= "Unknown state";
264 rtos
->thread_details
[tasks_found
].extra_info_str
= malloc(strlen(
266 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
, state_desc
);
268 rtos
->thread_details
[tasks_found
].exists
= true;
270 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
273 prev_thread_ptr
= thread_index
;
275 /* Get the location of the next thread structure. */
276 thread_index
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
277 retval
= target_read_buffer(rtos
->target
,
278 prev_thread_ptr
+ param
->thread_next_offset
,
279 param
->pointer_width
,
280 (uint8_t *) &thread_index
);
281 if (retval
!= ERROR_OK
) {
282 LOG_ERROR("Error reading next thread pointer in eCos thread list");
285 } while (thread_index
!= first_thread
);
287 rtos
->thread_count
= tasks_found
;
291 static int eCos_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
294 const struct eCos_params
*param
;
296 *hex_reg_list
= NULL
;
304 if (rtos
->rtos_specific_params
== NULL
)
307 param
= (const struct eCos_params
*) rtos
->rtos_specific_params
;
309 /* Find the thread with that thread id */
311 uint32_t thread_list_head
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
312 uint32_t thread_index
;
313 target_read_buffer(rtos
->target
, thread_list_head
, param
->pointer_width
,
314 (uint8_t *)&thread_index
);
317 retval
= target_read_buffer(rtos
->target
,
318 thread_index
+ param
->thread_uniqueid_offset
,
321 if (retval
!= ERROR_OK
) {
322 LOG_ERROR("Error reading unique id from eCos thread");
326 if (id
== thread_id
) {
330 target_read_buffer(rtos
->target
,
331 thread_index
+ param
->thread_next_offset
,
332 param
->pointer_width
,
333 (uint8_t *) &thread_index
);
337 /* Read the stack pointer */
338 int64_t stack_ptr
= 0;
339 retval
= target_read_buffer(rtos
->target
,
340 thread_index
+ param
->thread_stack_offset
,
341 param
->pointer_width
,
342 (uint8_t *)&stack_ptr
);
343 if (retval
!= ERROR_OK
) {
344 LOG_ERROR("Error reading stack frame from eCos thread");
348 return rtos_generic_stack_read(rtos
->target
,
349 param
->stacking_info
,
357 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
360 *symbol_list
= calloc(
361 ARRAY_SIZE(eCos_symbol_list
), sizeof(symbol_table_elem_t
));
363 for (i
= 0; i
< ARRAY_SIZE(eCos_symbol_list
); i
++)
364 (*symbol_list
)[i
].symbol_name
= eCos_symbol_list
[i
];
369 static int eCos_detect_rtos(struct target
*target
)
371 if ((target
->rtos
->symbols
!= NULL
) &&
372 (target
->rtos
->symbols
[eCos_VAL_thread_list
].address
!= 0)) {
373 /* looks like eCos */
379 static int eCos_create(struct target
*target
)
382 while ((i
< ECOS_NUM_PARAMS
) &&
383 (0 != strcmp(eCos_params_list
[i
].target_name
, target
->type
->name
))) {
386 if (i
>= ECOS_NUM_PARAMS
) {
387 LOG_ERROR("Could not find target in eCos compatibility list");
391 target
->rtos
->rtos_specific_params
= (void *) &eCos_params_list
[i
];
392 target
->rtos
->current_thread
= 0;
393 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)