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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "rtos_ecos_stackings.h"
31 static int eCos_detect_rtos(struct target
*target
);
32 static int eCos_create(struct target
*target
);
33 static int eCos_update_threads(struct rtos
*rtos
);
34 static int eCos_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
);
35 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
37 struct eCos_thread_state
{
42 struct eCos_thread_state eCos_thread_states
[] = {
51 #define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state))
55 unsigned char pointer_width
;
56 unsigned char thread_stack_offset
;
57 unsigned char thread_name_offset
;
58 unsigned char thread_state_offset
;
59 unsigned char thread_next_offset
;
60 unsigned char thread_uniqueid_offset
;
61 const struct rtos_register_stacking
*stacking_info
;
64 const struct eCos_params eCos_params_list
[] = {
66 "cortex_m3", /* target_name */
67 4, /* pointer_width; */
68 0x0c, /* thread_stack_offset; */
69 0x9c, /* thread_name_offset; */
70 0x3c, /* thread_state_offset; */
71 0xa0, /* thread_next_offset */
72 0x4c, /* thread_uniqueid_offset */
73 &rtos_eCos_Cortex_M3_stacking
/* stacking_info */
77 #define ECOS_NUM_PARAMS ((int)(sizeof(eCos_params_list)/sizeof(struct eCos_params)))
79 enum eCos_symbol_values
{
80 eCos_VAL_thread_list
= 0,
81 eCos_VAL_current_thread_ptr
= 1
84 static char *eCos_symbol_list
[] = {
85 "Cyg_Thread::thread_list",
86 "Cyg_Scheduler_Base::current_thread",
90 #define ECOS_NUM_SYMBOLS (sizeof(eCos_symbol_list)/sizeof(char *))
92 const struct rtos_type eCos_rtos
= {
95 .detect_rtos
= eCos_detect_rtos
,
96 .create
= eCos_create
,
97 .update_threads
= eCos_update_threads
,
98 .get_thread_reg_list
= eCos_get_thread_reg_list
,
99 .get_symbol_list_to_lookup
= eCos_get_symbol_list_to_lookup
,
103 static int eCos_update_threads(struct rtos
*rtos
)
107 int thread_list_size
= 0;
108 const struct eCos_params
*param
;
113 if (rtos
->rtos_specific_params
== NULL
)
116 param
= (const struct eCos_params
*) rtos
->rtos_specific_params
;
118 if (rtos
->symbols
== NULL
) {
119 LOG_OUTPUT("No symbols for eCos\r\n");
123 if (rtos
->symbols
[eCos_VAL_thread_list
].address
== 0) {
124 LOG_OUTPUT("Don't have the thread list head\r\n");
128 /* wipe out previous thread details if any */
129 if (rtos
->thread_details
!= NULL
) {
131 for (j
= 0; j
< rtos
->thread_count
; j
++) {
132 if (rtos
->thread_details
[j
].display_str
!= NULL
) {
133 free(rtos
->thread_details
[j
].display_str
);
134 rtos
->thread_details
[j
].display_str
= NULL
;
136 if (rtos
->thread_details
[j
].thread_name_str
!= NULL
) {
137 free(rtos
->thread_details
[j
].thread_name_str
);
138 rtos
->thread_details
[j
].thread_name_str
= NULL
;
140 if (rtos
->thread_details
[j
].extra_info_str
!= NULL
) {
141 free(rtos
->thread_details
[j
].extra_info_str
);
142 rtos
->thread_details
[j
].extra_info_str
= NULL
;
145 free(rtos
->thread_details
);
146 rtos
->thread_details
= NULL
;
149 /* determine the number of current threads */
150 uint32_t thread_list_head
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
151 uint32_t thread_index
;
152 target_read_buffer(rtos
->target
,
154 param
->pointer_width
,
155 (uint8_t *) &thread_index
);
156 uint32_t first_thread
= thread_index
;
159 retval
= target_read_buffer(rtos
->target
,
160 thread_index
+ param
->thread_next_offset
,
161 param
->pointer_width
,
162 (uint8_t *) &thread_index
);
163 if (retval
!= ERROR_OK
)
165 } while (thread_index
!= first_thread
);
167 /* read the current thread id */
168 uint32_t current_thread_addr
;
169 retval
= target_read_buffer(rtos
->target
,
170 rtos
->symbols
[eCos_VAL_current_thread_ptr
].address
,
172 (uint8_t *)¤t_thread_addr
);
173 if (retval
!= ERROR_OK
)
175 rtos
->current_thread
= 0;
176 retval
= target_read_buffer(rtos
->target
,
177 current_thread_addr
+ param
->thread_uniqueid_offset
,
179 (uint8_t *)&rtos
->current_thread
);
180 if (retval
!= ERROR_OK
) {
181 LOG_OUTPUT("Could not read eCos current thread from target\r\n");
185 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
186 /* Either : No RTOS threads - there is always at least the current execution though */
187 /* OR : No current thread - all threads suspended - show the current execution
189 char tmp_str
[] = "Current Execution";
192 rtos
->thread_details
= (struct thread_detail
*) malloc(
193 sizeof(struct thread_detail
) * thread_list_size
);
194 rtos
->thread_details
->threadid
= 1;
195 rtos
->thread_details
->exists
= true;
196 rtos
->thread_details
->display_str
= NULL
;
197 rtos
->thread_details
->extra_info_str
= NULL
;
198 rtos
->thread_details
->thread_name_str
= (char *) malloc(sizeof(tmp_str
));
199 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
201 if (thread_list_size
== 0) {
202 rtos
->thread_count
= 1;
206 /* create space for new thread details */
207 rtos
->thread_details
= (struct thread_detail
*) malloc(
208 sizeof(struct thread_detail
) * thread_list_size
);
211 /* loop over all threads */
212 thread_index
= first_thread
;
215 #define ECOS_THREAD_NAME_STR_SIZE (200)
216 char tmp_str
[ECOS_THREAD_NAME_STR_SIZE
];
218 uint32_t name_ptr
= 0;
219 uint32_t prev_thread_ptr
;
221 /* Save the thread pointer */
223 retval
= target_read_buffer(rtos
->target
,
224 thread_index
+ param
->thread_uniqueid_offset
,
226 (uint8_t *)&thread_id
);
227 if (retval
!= ERROR_OK
) {
228 LOG_OUTPUT("Could not read eCos thread id from target\r\n");
231 rtos
->thread_details
[tasks_found
].threadid
= thread_id
;
233 /* read the name pointer */
234 retval
= target_read_buffer(rtos
->target
,
235 thread_index
+ param
->thread_name_offset
,
236 param
->pointer_width
,
237 (uint8_t *)&name_ptr
);
238 if (retval
!= ERROR_OK
) {
239 LOG_OUTPUT("Could not read eCos thread name pointer from target\r\n");
243 /* Read the thread name */
245 target_read_buffer(rtos
->target
,
247 ECOS_THREAD_NAME_STR_SIZE
,
248 (uint8_t *)&tmp_str
);
249 if (retval
!= ERROR_OK
) {
250 LOG_OUTPUT("Error reading thread name from eCos target\r\n");
253 tmp_str
[ECOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
255 if (tmp_str
[0] == '\x00')
256 strcpy(tmp_str
, "No Name");
258 rtos
->thread_details
[tasks_found
].thread_name_str
=
259 (char *)malloc(strlen(tmp_str
)+1);
260 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
262 /* Read the thread status */
263 int64_t thread_status
= 0;
264 retval
= target_read_buffer(rtos
->target
,
265 thread_index
+ param
->thread_state_offset
,
267 (uint8_t *)&thread_status
);
268 if (retval
!= ERROR_OK
) {
269 LOG_OUTPUT("Error reading thread state from eCos target\r\n");
273 for (i
= 0; (i
< ECOS_NUM_STATES
) && (eCos_thread_states
[i
].value
!= thread_status
); i
++) {
280 if (i
< ECOS_NUM_STATES
)
281 state_desc
= eCos_thread_states
[i
].desc
;
283 state_desc
= "Unknown state";
285 rtos
->thread_details
[tasks_found
].extra_info_str
= (char *)malloc(strlen(
287 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
, state_desc
);
289 rtos
->thread_details
[tasks_found
].exists
= true;
291 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
294 prev_thread_ptr
= thread_index
;
296 /* Get the location of the next thread structure. */
297 thread_index
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
298 retval
= target_read_buffer(rtos
->target
,
299 prev_thread_ptr
+ param
->thread_next_offset
,
300 param
->pointer_width
,
301 (uint8_t *) &thread_index
);
302 if (retval
!= ERROR_OK
) {
303 LOG_OUTPUT("Error reading next thread pointer in eCos thread list\r\n");
306 } while (thread_index
!= first_thread
);
308 rtos
->thread_count
= tasks_found
;
312 static int eCos_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
315 const struct eCos_params
*param
;
317 *hex_reg_list
= NULL
;
325 if (rtos
->rtos_specific_params
== NULL
)
328 param
= (const struct eCos_params
*) rtos
->rtos_specific_params
;
330 /* Find the thread with that thread id */
332 uint32_t thread_list_head
= rtos
->symbols
[eCos_VAL_thread_list
].address
;
333 uint32_t thread_index
;
334 target_read_buffer(rtos
->target
, thread_list_head
, param
->pointer_width
,
335 (uint8_t *)&thread_index
);
338 retval
= target_read_buffer(rtos
->target
,
339 thread_index
+ param
->thread_uniqueid_offset
,
342 if (retval
!= ERROR_OK
) {
343 LOG_OUTPUT("Error reading unique id from eCos thread\r\n");
347 if (id
== thread_id
) {
351 target_read_buffer(rtos
->target
,
352 thread_index
+ param
->thread_next_offset
,
353 param
->pointer_width
,
354 (uint8_t *) &thread_index
);
358 /* Read the stack pointer */
359 int64_t stack_ptr
= 0;
360 retval
= target_read_buffer(rtos
->target
,
361 thread_index
+ param
->thread_stack_offset
,
362 param
->pointer_width
,
363 (uint8_t *)&stack_ptr
);
364 if (retval
!= ERROR_OK
) {
365 LOG_OUTPUT("Error reading stack frame from eCos thread\r\n");
369 return rtos_generic_stack_read(rtos
->target
,
370 param
->stacking_info
,
378 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
381 *symbol_list
= (symbol_table_elem_t
*) malloc(
382 sizeof(symbol_table_elem_t
) * ECOS_NUM_SYMBOLS
);
384 for (i
= 0; i
< ECOS_NUM_SYMBOLS
; i
++)
385 (*symbol_list
)[i
].symbol_name
= eCos_symbol_list
[i
];
390 static int eCos_detect_rtos(struct target
*target
)
392 if ((target
->rtos
->symbols
!= NULL
) &&
393 (target
->rtos
->symbols
[eCos_VAL_thread_list
].address
!= 0)) {
394 /* looks like eCos */
400 static int eCos_create(struct target
*target
)
403 while ((i
< ECOS_NUM_PARAMS
) &&
404 (0 != strcmp(eCos_params_list
[i
].target_name
, target
->type
->name
))) {
407 if (i
>= ECOS_NUM_PARAMS
) {
408 LOG_OUTPUT("Could not find target in eCos compatibility list\r\n");
412 target
->rtos
->rtos_specific_params
= (void *) &eCos_params_list
[i
];
413 target
->rtos
->current_thread
= 0;
414 target
->rtos
->thread_details
= NULL
;