7964712f8b2620e76d555d123869461d20a94f15
[openocd.git] / src / rtos / eCos.c
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 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
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 "helper/types.h"
30 #include "rtos_ecos_stackings.h"
31
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[]);
37
38 struct eCos_thread_state {
39 int value;
40 char *desc;
41 };
42
43 struct eCos_thread_state eCos_thread_states[] = {
44 { 0, "Ready" },
45 { 1, "Sleeping" },
46 { 2, "Countsleep" },
47 { 4, "Suspended" },
48 { 8, "Creating" },
49 { 16, "Exited" }
50 };
51
52 #define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state))
53
54 struct eCos_params {
55 char *target_name;
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;
63 };
64
65 const struct eCos_params eCos_params_list[] = {
66 {
67 "cortex_m3", /* 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 */
75 }
76 };
77
78 #define ECOS_NUM_PARAMS ((int)(sizeof(eCos_params_list)/sizeof(struct eCos_params)))
79
80 enum eCos_symbol_values {
81 eCos_VAL_thread_list = 0,
82 eCos_VAL_current_thread_ptr = 1
83 };
84
85 static char *eCos_symbol_list[] = {
86 "Cyg_Thread::thread_list",
87 "Cyg_Scheduler_Base::current_thread",
88 NULL
89 };
90
91 const struct rtos_type eCos_rtos = {
92 .name = "eCos",
93
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,
99
100 };
101
102 static int eCos_update_threads(struct rtos *rtos)
103 {
104 int retval;
105 int tasks_found = 0;
106 int thread_list_size = 0;
107 const struct eCos_params *param;
108
109 if (rtos == NULL)
110 return -1;
111
112 if (rtos->rtos_specific_params == NULL)
113 return -3;
114
115 param = (const struct eCos_params *) rtos->rtos_specific_params;
116
117 if (rtos->symbols == NULL) {
118 LOG_OUTPUT("No symbols for eCos\r\n");
119 return -4;
120 }
121
122 if (rtos->symbols[eCos_VAL_thread_list].address == 0) {
123 LOG_OUTPUT("Don't have the thread list head\r\n");
124 return -2;
125 }
126
127 /* wipe out previous thread details if any */
128 if (rtos->thread_details != NULL) {
129 int j;
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;
134 }
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;
138 }
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;
142 }
143 }
144 free(rtos->thread_details);
145 rtos->thread_details = NULL;
146 }
147
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,
152 thread_list_head,
153 param->pointer_width,
154 (uint8_t *) &thread_index);
155 uint32_t first_thread = thread_index;
156 do {
157 thread_list_size++;
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)
163 return retval;
164 } while (thread_index != first_thread);
165
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,
170 4,
171 (uint8_t *)&current_thread_addr);
172 if (retval != ERROR_OK)
173 return retval;
174 rtos->current_thread = 0;
175 retval = target_read_buffer(rtos->target,
176 current_thread_addr + param->thread_uniqueid_offset,
177 2,
178 (uint8_t *)&rtos->current_thread);
179 if (retval != ERROR_OK) {
180 LOG_OUTPUT("Could not read eCos current thread from target\r\n");
181 return retval;
182 }
183
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
187 * of idling */
188 char tmp_str[] = "Current Execution";
189 thread_list_size++;
190 tasks_found++;
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);
199
200 if (thread_list_size == 0) {
201 rtos->thread_count = 1;
202 return ERROR_OK;
203 }
204 } else {
205 /* create space for new thread details */
206 rtos->thread_details = (struct thread_detail *) malloc(
207 sizeof(struct thread_detail) * thread_list_size);
208 }
209
210 /* loop over all threads */
211 thread_index = first_thread;
212 do {
213
214 #define ECOS_THREAD_NAME_STR_SIZE (200)
215 char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
216 unsigned int i = 0;
217 uint32_t name_ptr = 0;
218 uint32_t prev_thread_ptr;
219
220 /* Save the thread pointer */
221 uint16_t thread_id;
222 retval = target_read_buffer(rtos->target,
223 thread_index + param->thread_uniqueid_offset,
224 2,
225 (uint8_t *)&thread_id);
226 if (retval != ERROR_OK) {
227 LOG_OUTPUT("Could not read eCos thread id from target\r\n");
228 return retval;
229 }
230 rtos->thread_details[tasks_found].threadid = thread_id;
231
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_OUTPUT("Could not read eCos thread name pointer from target\r\n");
239 return retval;
240 }
241
242 /* Read the thread name */
243 retval =
244 target_read_buffer(rtos->target,
245 name_ptr,
246 ECOS_THREAD_NAME_STR_SIZE,
247 (uint8_t *)&tmp_str);
248 if (retval != ERROR_OK) {
249 LOG_OUTPUT("Error reading thread name from eCos target\r\n");
250 return retval;
251 }
252 tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
253
254 if (tmp_str[0] == '\x00')
255 strcpy(tmp_str, "No Name");
256
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);
260
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,
265 4,
266 (uint8_t *)&thread_status);
267 if (retval != ERROR_OK) {
268 LOG_OUTPUT("Error reading thread state from eCos target\r\n");
269 return retval;
270 }
271
272 for (i = 0; (i < ECOS_NUM_STATES) && (eCos_thread_states[i].value != thread_status); i++) {
273 /*
274 * empty
275 */
276 }
277
278 char *state_desc;
279 if (i < ECOS_NUM_STATES)
280 state_desc = eCos_thread_states[i].desc;
281 else
282 state_desc = "Unknown state";
283
284 rtos->thread_details[tasks_found].extra_info_str = (char *)malloc(strlen(
285 state_desc)+1);
286 strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc);
287
288 rtos->thread_details[tasks_found].exists = true;
289
290 rtos->thread_details[tasks_found].display_str = NULL;
291
292 tasks_found++;
293 prev_thread_ptr = thread_index;
294
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_OUTPUT("Error reading next thread pointer in eCos thread list\r\n");
303 return retval;
304 }
305 } while (thread_index != first_thread);
306
307 rtos->thread_count = tasks_found;
308 return 0;
309 }
310
311 static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
312 {
313 int retval;
314 const struct eCos_params *param;
315
316 *hex_reg_list = NULL;
317
318 if (rtos == NULL)
319 return -1;
320
321 if (thread_id == 0)
322 return -2;
323
324 if (rtos->rtos_specific_params == NULL)
325 return -3;
326
327 param = (const struct eCos_params *) rtos->rtos_specific_params;
328
329 /* Find the thread with that thread id */
330 uint16_t id = 0;
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);
335 bool done = false;
336 while (!done) {
337 retval = target_read_buffer(rtos->target,
338 thread_index + param->thread_uniqueid_offset,
339 2,
340 (uint8_t *)&id);
341 if (retval != ERROR_OK) {
342 LOG_OUTPUT("Error reading unique id from eCos thread\r\n");
343 return retval;
344 }
345
346 if (id == thread_id) {
347 done = true;
348 break;
349 }
350 target_read_buffer(rtos->target,
351 thread_index + param->thread_next_offset,
352 param->pointer_width,
353 (uint8_t *) &thread_index);
354 }
355
356 if (done) {
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_OUTPUT("Error reading stack frame from eCos thread\r\n");
365 return retval;
366 }
367
368 return rtos_generic_stack_read(rtos->target,
369 param->stacking_info,
370 stack_ptr,
371 hex_reg_list);
372 }
373
374 return -1;
375 }
376
377 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
378 {
379 unsigned int i;
380 *symbol_list = (symbol_table_elem_t *) malloc(
381 sizeof(symbol_table_elem_t) * ARRAY_SIZE(eCos_symbol_list));
382
383 for (i = 0; i < ARRAY_SIZE(eCos_symbol_list); i++)
384 (*symbol_list)[i].symbol_name = eCos_symbol_list[i];
385
386 return 0;
387 }
388
389 static int eCos_detect_rtos(struct target *target)
390 {
391 if ((target->rtos->symbols != NULL) &&
392 (target->rtos->symbols[eCos_VAL_thread_list].address != 0)) {
393 /* looks like eCos */
394 return 1;
395 }
396 return 0;
397 }
398
399 static int eCos_create(struct target *target)
400 {
401 int i = 0;
402 while ((i < ECOS_NUM_PARAMS) &&
403 (0 != strcmp(eCos_params_list[i].target_name, target->type->name))) {
404 i++;
405 }
406 if (i >= ECOS_NUM_PARAMS) {
407 LOG_OUTPUT("Could not find target in eCos compatibility list\r\n");
408 return -1;
409 }
410
411 target->rtos->rtos_specific_params = (void *) &eCos_params_list[i];
412 target->rtos->current_thread = 0;
413 target->rtos->thread_details = NULL;
414 return 0;
415 }

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)