build: cleanup src/rtos directory
[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 "rtos_ecos_stackings.h"
30
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[]);
36
37 struct eCos_thread_state {
38 int value;
39 char *desc;
40 };
41
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" }
49 };
50
51 #define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state))
52
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;
62 };
63
64 const struct eCos_params eCos_params_list[] = {
65 {
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 */
74 }
75 };
76
77 #define ECOS_NUM_PARAMS ((int)(sizeof(eCos_params_list)/sizeof(struct eCos_params)))
78
79 enum eCos_symbol_values {
80 eCos_VAL_thread_list = 0,
81 eCos_VAL_current_thread_ptr = 1
82 };
83
84 static char *eCos_symbol_list[] = {
85 "Cyg_Thread::thread_list",
86 "Cyg_Scheduler_Base::current_thread",
87 NULL
88 };
89
90 #define ECOS_NUM_SYMBOLS (sizeof(eCos_symbol_list)/sizeof(char *))
91
92 const struct rtos_type eCos_rtos = {
93 .name = "eCos",
94
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,
100
101 };
102
103 static int eCos_update_threads(struct rtos *rtos)
104 {
105 int retval;
106 int tasks_found = 0;
107 int thread_list_size = 0;
108 const struct eCos_params *param;
109
110 if (rtos == NULL)
111 return -1;
112
113 if (rtos->rtos_specific_params == NULL)
114 return -3;
115
116 param = (const struct eCos_params *) rtos->rtos_specific_params;
117
118 if (rtos->symbols == NULL) {
119 LOG_OUTPUT("No symbols for eCos\r\n");
120 return -4;
121 }
122
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;
126 }
127
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;
135 }
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;
139 }
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;
143 }
144 }
145 free(rtos->thread_details);
146 rtos->thread_details = NULL;
147 }
148
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);
166
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,
171 4,
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,
178 2,
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;
183 }
184
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);
200
201 if (thread_list_size == 0) {
202 rtos->thread_count = 1;
203 return ERROR_OK;
204 }
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);
209 }
210
211 /* loop over all threads */
212 thread_index = first_thread;
213 do {
214
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;
220
221 /* Save the thread pointer */
222 uint16_t thread_id;
223 retval = target_read_buffer(rtos->target,
224 thread_index + param->thread_uniqueid_offset,
225 2,
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;
230 }
231 rtos->thread_details[tasks_found].threadid = thread_id;
232
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;
241 }
242
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;
252 }
253 tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
254
255 if (tmp_str[0] == '\x00')
256 strcpy(tmp_str, "No Name");
257
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);
261
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,
266 4,
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;
271 }
272
273 for (i = 0; (i < ECOS_NUM_STATES) && (eCos_thread_states[i].value != thread_status); i++) {
274 /*
275 * empty
276 */
277 }
278
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";
284
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);
288
289 rtos->thread_details[tasks_found].exists = true;
290
291 rtos->thread_details[tasks_found].display_str = NULL;
292
293 tasks_found++;
294 prev_thread_ptr = thread_index;
295
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;
305 }
306 } while (thread_index != first_thread);
307
308 rtos->thread_count = tasks_found;
309 return 0;
310 }
311
312 static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
313 {
314 int retval;
315 const struct eCos_params *param;
316
317 *hex_reg_list = NULL;
318
319 if (rtos == NULL)
320 return -1;
321
322 if (thread_id == 0)
323 return -2;
324
325 if (rtos->rtos_specific_params == NULL)
326 return -3;
327
328 param = (const struct eCos_params *) rtos->rtos_specific_params;
329
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,
340 2,
341 (uint8_t *)&id);
342 if (retval != ERROR_OK) {
343 LOG_OUTPUT("Error reading unique id from eCos thread\r\n");
344 return retval;
345 }
346
347 if (id == thread_id) {
348 done = true;
349 break;
350 }
351 target_read_buffer(rtos->target,
352 thread_index + param->thread_next_offset,
353 param->pointer_width,
354 (uint8_t *) &thread_index);
355 }
356
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;
367 }
368
369 return rtos_generic_stack_read(rtos->target,
370 param->stacking_info,
371 stack_ptr,
372 hex_reg_list);
373 }
374
375 return -1;
376 }
377
378 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
379 {
380 unsigned int i;
381 *symbol_list = (symbol_table_elem_t *) malloc(
382 sizeof(symbol_table_elem_t) * ECOS_NUM_SYMBOLS);
383
384 for (i = 0; i < ECOS_NUM_SYMBOLS; i++)
385 (*symbol_list)[i].symbol_name = eCos_symbol_list[i];
386
387 return 0;
388 }
389
390 static int eCos_detect_rtos(struct target *target)
391 {
392 if ((target->rtos->symbols != NULL) &&
393 (target->rtos->symbols[eCos_VAL_thread_list].address != 0)) {
394 /* looks like eCos */
395 return 1;
396 }
397 return 0;
398 }
399
400 static int eCos_create(struct target *target)
401 {
402 int i = 0;
403 while ((i < ECOS_NUM_PARAMS) &&
404 (0 != strcmp(eCos_params_list[i].target_name, target->type->name))) {
405 i++;
406 }
407 if (i >= ECOS_NUM_PARAMS) {
408 LOG_OUTPUT("Could not find target in eCos compatibility list\r\n");
409 return -1;
410 }
411
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;
416 }

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)