stlink: add myself to copyright header
[openocd/cederom.git] / src / rtos / eCos.c
blob5c18916a12ee58908413bd4410f8ede84cb08d7c
1 /***************************************************************************
2 * *
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. *
7 * *
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. *
12 * *
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 ***************************************************************************/
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
23 #include <helper/time_support.h>
24 #include <jtag/jtag.h>
25 #include "target/target.h"
26 #include "target/target_type.h"
27 #include "rtos.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 {
38 int value;
39 char *desc;
42 struct eCos_thread_state eCos_thread_states[] = {
43 { 0, "Ready" },
44 { 1, "Sleeping" },
45 { 2, "Countsleep" },
46 { 4, "Suspended" },
47 { 8, "Creating" },
48 { 16, "Exited" }
51 #define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state))
53 struct eCos_params {
54 char *target_name;
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",
87 NULL
90 #define ECOS_NUM_SYMBOLS (sizeof(eCos_symbol_list)/sizeof(char *))
92 const struct rtos_type eCos_rtos = {
93 .name = "eCos",
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)
105 int retval;
106 int tasks_found = 0;
107 int thread_list_size = 0;
108 const struct eCos_params *param;
110 if (rtos == NULL)
111 return -1;
113 if (rtos->rtos_specific_params == NULL)
114 return -3;
116 param = (const struct eCos_params *) rtos->rtos_specific_params;
118 if (rtos->symbols == NULL) {
119 LOG_OUTPUT("No symbols for eCos\r\n");
120 return -4;
123 if (rtos->symbols[eCos_VAL_thread_list].address == 0) {
124 LOG_OUTPUT("Don't have the thread list head\r\n");
125 return -2;
128 /* wipe out previous thread details if any */
129 if (rtos->thread_details != NULL) {
130 int j;
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,
153 thread_list_head,
154 param->pointer_width,
155 (uint8_t *) &thread_index);
156 uint32_t first_thread = thread_index;
157 do {
158 thread_list_size++;
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)
164 return retval;
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 *)&current_thread_addr);
173 if (retval != ERROR_OK)
174 return retval;
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");
182 return retval;
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
188 * of idling */
189 char tmp_str[] = "Current Execution";
190 thread_list_size++;
191 tasks_found++;
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;
203 return ERROR_OK;
205 } else {
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;
213 do {
215 #define ECOS_THREAD_NAME_STR_SIZE (200)
216 char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
217 unsigned int i = 0;
218 uint32_t name_ptr = 0;
219 uint32_t prev_thread_ptr;
221 /* Save the thread pointer */
222 uint16_t thread_id;
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");
229 return retval;
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");
240 return retval;
243 /* Read the thread name */
244 retval =
245 target_read_buffer(rtos->target,
246 name_ptr,
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");
251 return retval;
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");
270 return retval;
273 for (i = 0; (i < ECOS_NUM_STATES) && (eCos_thread_states[i].value != thread_status); i++) {
275 * empty
279 char *state_desc;
280 if (i < ECOS_NUM_STATES)
281 state_desc = eCos_thread_states[i].desc;
282 else
283 state_desc = "Unknown state";
285 rtos->thread_details[tasks_found].extra_info_str = (char *)malloc(strlen(
286 state_desc)+1);
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;
293 tasks_found++;
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");
304 return retval;
306 } while (thread_index != first_thread);
308 rtos->thread_count = tasks_found;
309 return 0;
312 static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
314 int retval;
315 const struct eCos_params *param;
317 *hex_reg_list = NULL;
319 if (rtos == NULL)
320 return -1;
322 if (thread_id == 0)
323 return -2;
325 if (rtos->rtos_specific_params == NULL)
326 return -3;
328 param = (const struct eCos_params *) rtos->rtos_specific_params;
330 /* Find the thread with that thread id */
331 uint16_t id = 0;
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);
336 bool done = false;
337 while (!done) {
338 retval = target_read_buffer(rtos->target,
339 thread_index + param->thread_uniqueid_offset,
341 (uint8_t *)&id);
342 if (retval != ERROR_OK) {
343 LOG_OUTPUT("Error reading unique id from eCos thread\r\n");
344 return retval;
347 if (id == thread_id) {
348 done = true;
349 break;
351 target_read_buffer(rtos->target,
352 thread_index + param->thread_next_offset,
353 param->pointer_width,
354 (uint8_t *) &thread_index);
357 if (done) {
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");
366 return retval;
369 return rtos_generic_stack_read(rtos->target,
370 param->stacking_info,
371 stack_ptr,
372 hex_reg_list);
375 return -1;
378 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
380 unsigned int i;
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];
387 return 0;
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 */
395 return 1;
397 return 0;
400 static int eCos_create(struct target *target)
402 int i = 0;
403 while ((i < ECOS_NUM_PARAMS) &&
404 (0 != strcmp(eCos_params_list[i].target_name, target->type->name))) {
405 i++;
407 if (i >= ECOS_NUM_PARAMS) {
408 LOG_OUTPUT("Could not find target in eCos compatibility list\r\n");
409 return -1;
412 target->rtos->rtos_specific_params = (void *) &eCos_params_list[i];
413 target->rtos->current_thread = 0;
414 target->rtos->thread_details = NULL;
415 return 0;