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 bool 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
->extra_info_str
= NULL
;
176 rtos
->thread_details
->thread_name_str
= malloc(sizeof(tmp_str
));
177 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
179 if (thread_list_size
== 0) {
180 rtos
->thread_count
= 1;
184 /* create space for new thread details */
185 rtos
->thread_details
= malloc(
186 sizeof(struct thread_detail
) * thread_list_size
);
189 /* loop over all threads */
190 thread_index
= first_thread
;
193 #define ECOS_THREAD_NAME_STR_SIZE (200)
194 char tmp_str
[ECOS_THREAD_NAME_STR_SIZE
];
196 uint32_t name_ptr
= 0;
197 uint32_t prev_thread_ptr
;
199 /* Save the thread pointer */
201 retval
= target_read_buffer(rtos
->target
,
202 thread_index
+ param
->thread_uniqueid_offset
,
204 (uint8_t *)&thread_id
);
205 if (retval
!= ERROR_OK
) {
206 LOG_ERROR("Could not read eCos thread id from target");
209 rtos
->thread_details
[tasks_found
].threadid
= thread_id
;
211 /* read the name pointer */
212 retval
= target_read_buffer(rtos
->target
,
213 thread_index
+ param
->thread_name_offset
,
214 param
->pointer_width
,
215 (uint8_t *)&name_ptr
);
216 if (retval
!= ERROR_OK
) {
217 LOG_ERROR("Could not read eCos thread name pointer from target");
221 /* Read the thread name */
223 target_read_buffer(rtos
->target
,
225 ECOS_THREAD_NAME_STR_SIZE
,
226 (uint8_t *)&tmp_str
);
227 if (retval
!= ERROR_OK
) {
228 LOG_ERROR("Error reading thread name from eCos target");
231 tmp_str
[ECOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
233 if (tmp_str
[0] == '\x00')
234 strcpy(tmp_str
, "No Name");
236 rtos
->thread_details
[tasks_found
].thread_name_str
=
237 malloc(strlen(tmp_str
)+1);
238 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
240 /* Read the thread status */
241 int64_t thread_status
= 0;
242 retval
= target_read_buffer(rtos
->target
,
243 thread_index
+ param
->thread_state_offset
,
245 (uint8_t *)&thread_status
);
246 if (retval
!= ERROR_OK
) {
247 LOG_ERROR("Error reading thread state from eCos target");
251 for (i
= 0; (i
< ECOS_NUM_STATES
) && (eCos_thread_states
[i
].value
!= thread_status
); i
++) {
257 const char *state_desc
;
258 if (i
< ECOS_NUM_STATES
)
259 state_desc
= eCos_thread_states
[i
].desc
;
261 state_desc
= "Unknown state";
263 rtos
->thread_details
[tasks_found
].extra_info_str
= malloc(strlen(
265 sprintf(rtos
->thread_details
[tasks_found
].extra_info_str
, "State: %s", state_desc
);
267 rtos
->thread_details
[tasks_found
].exists
= true;
270 prev_thread_ptr
= thread_index
;
272 /* Get the location of the next thread structure. */
273 thread_index
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
274 retval
= target_read_buffer(rtos
->target
,
275 prev_thread_ptr
+ param
->thread_next_offset
,
276 param
->pointer_width
,
277 (uint8_t *) &thread_index
);
278 if (retval
!= ERROR_OK
) {
279 LOG_ERROR("Error reading next thread pointer in eCos thread list");
282 } while (thread_index
!= first_thread
);
284 rtos
->thread_count
= tasks_found
;
288 static int eCos_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
291 const struct eCos_params
*param
;
293 *hex_reg_list
= NULL
;
301 if (rtos
->rtos_specific_params
== NULL
)
304 param
= (const struct eCos_params
*) rtos
->rtos_specific_params
;
306 /* Find the thread with that thread id */
308 uint32_t thread_list_head
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
309 uint32_t thread_index
;
310 target_read_buffer(rtos
->target
, thread_list_head
, param
->pointer_width
,
311 (uint8_t *)&thread_index
);
314 retval
= target_read_buffer(rtos
->target
,
315 thread_index
+ param
->thread_uniqueid_offset
,
318 if (retval
!= ERROR_OK
) {
319 LOG_ERROR("Error reading unique id from eCos thread");
323 if (id
== thread_id
) {
327 target_read_buffer(rtos
->target
,
328 thread_index
+ param
->thread_next_offset
,
329 param
->pointer_width
,
330 (uint8_t *) &thread_index
);
334 /* Read the stack pointer */
335 int64_t stack_ptr
= 0;
336 retval
= target_read_buffer(rtos
->target
,
337 thread_index
+ param
->thread_stack_offset
,
338 param
->pointer_width
,
339 (uint8_t *)&stack_ptr
);
340 if (retval
!= ERROR_OK
) {
341 LOG_ERROR("Error reading stack frame from eCos thread");
345 return rtos_generic_stack_read(rtos
->target
,
346 param
->stacking_info
,
354 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
357 *symbol_list
= calloc(
358 ARRAY_SIZE(eCos_symbol_list
), sizeof(symbol_table_elem_t
));
360 for (i
= 0; i
< ARRAY_SIZE(eCos_symbol_list
); i
++)
361 (*symbol_list
)[i
].symbol_name
= eCos_symbol_list
[i
];
366 static bool eCos_detect_rtos(struct target
*target
)
368 if ((target
->rtos
->symbols
!= NULL
) &&
369 (target
->rtos
->symbols
[eCos_VAL_thread_list
].address
!= 0)) {
370 /* looks like eCos */
376 static int eCos_create(struct target
*target
)
379 while ((i
< ECOS_NUM_PARAMS
) &&
380 (0 != strcmp(eCos_params_list
[i
].target_name
, target
->type
->name
))) {
383 if (i
>= ECOS_NUM_PARAMS
) {
384 LOG_ERROR("Could not find target in eCos compatibility list");
388 target
->rtos
->rtos_specific_params
= (void *) &eCos_params_list
[i
];
389 target
->rtos
->current_thread
= 0;
390 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)