e4080695c0ab30045d1ec35a35f9f65e1965ad06
[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, see <http://www.gnu.org/licenses/>. *
15 ***************************************************************************/
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include <helper/time_support.h>
22 #include <jtag/jtag.h>
23 #include "target/target.h"
24 #include "target/target_type.h"
25 #include "rtos.h"
26 #include "helper/log.h"
27 #include "helper/types.h"
28 #include "rtos_ecos_stackings.h"
29
30 static int 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[]);
35
36 struct eCos_thread_state {
37 int value;
38 const char *desc;
39 };
40
41 static const struct eCos_thread_state eCos_thread_states[] = {
42 { 0, "Ready" },
43 { 1, "Sleeping" },
44 { 2, "Countsleep" },
45 { 4, "Suspended" },
46 { 8, "Creating" },
47 { 16, "Exited" }
48 };
49
50 #define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state))
51
52 struct eCos_params {
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;
61 };
62
63 static const struct eCos_params eCos_params_list[] = {
64 {
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 */
73 }
74 };
75
76 #define ECOS_NUM_PARAMS ((int)(sizeof(eCos_params_list)/sizeof(struct eCos_params)))
77
78 enum eCos_symbol_values {
79 eCos_VAL_thread_list = 0,
80 eCos_VAL_current_thread_ptr = 1
81 };
82
83 static const char * const eCos_symbol_list[] = {
84 "Cyg_Thread::thread_list",
85 "Cyg_Scheduler_Base::current_thread",
86 NULL
87 };
88
89 const struct rtos_type eCos_rtos = {
90 .name = "eCos",
91
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,
97
98 };
99
100 static int eCos_update_threads(struct rtos *rtos)
101 {
102 int retval;
103 int tasks_found = 0;
104 int thread_list_size = 0;
105 const struct eCos_params *param;
106
107 if (rtos == NULL)
108 return -1;
109
110 if (rtos->rtos_specific_params == NULL)
111 return -3;
112
113 param = (const struct eCos_params *) rtos->rtos_specific_params;
114
115 if (rtos->symbols == NULL) {
116 LOG_ERROR("No symbols for eCos");
117 return -4;
118 }
119
120 if (rtos->symbols[eCos_VAL_thread_list].address == 0) {
121 LOG_ERROR("Don't have the thread list head");
122 return -2;
123 }
124
125 /* wipe out previous thread details if any */
126 rtos_free_threadlist(rtos);
127
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,
132 thread_list_head,
133 param->pointer_width,
134 (uint8_t *) &thread_index);
135 uint32_t first_thread = thread_index;
136 do {
137 thread_list_size++;
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)
143 return retval;
144 } while (thread_index != first_thread);
145
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,
150 4,
151 (uint8_t *)&current_thread_addr);
152 if (retval != ERROR_OK)
153 return retval;
154 rtos->current_thread = 0;
155 retval = target_read_buffer(rtos->target,
156 current_thread_addr + param->thread_uniqueid_offset,
157 2,
158 (uint8_t *)&rtos->current_thread);
159 if (retval != ERROR_OK) {
160 LOG_ERROR("Could not read eCos current thread from target");
161 return retval;
162 }
163
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
167 * of idling */
168 char tmp_str[] = "Current Execution";
169 thread_list_size++;
170 tasks_found++;
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->display_str = NULL;
176 rtos->thread_details->extra_info_str = NULL;
177 rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
178 strcpy(rtos->thread_details->thread_name_str, tmp_str);
179
180 if (thread_list_size == 0) {
181 rtos->thread_count = 1;
182 return ERROR_OK;
183 }
184 } else {
185 /* create space for new thread details */
186 rtos->thread_details = malloc(
187 sizeof(struct thread_detail) * thread_list_size);
188 }
189
190 /* loop over all threads */
191 thread_index = first_thread;
192 do {
193
194 #define ECOS_THREAD_NAME_STR_SIZE (200)
195 char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
196 unsigned int i = 0;
197 uint32_t name_ptr = 0;
198 uint32_t prev_thread_ptr;
199
200 /* Save the thread pointer */
201 uint16_t thread_id;
202 retval = target_read_buffer(rtos->target,
203 thread_index + param->thread_uniqueid_offset,
204 2,
205 (uint8_t *)&thread_id);
206 if (retval != ERROR_OK) {
207 LOG_ERROR("Could not read eCos thread id from target");
208 return retval;
209 }
210 rtos->thread_details[tasks_found].threadid = thread_id;
211
212 /* read the name pointer */
213 retval = target_read_buffer(rtos->target,
214 thread_index + param->thread_name_offset,
215 param->pointer_width,
216 (uint8_t *)&name_ptr);
217 if (retval != ERROR_OK) {
218 LOG_ERROR("Could not read eCos thread name pointer from target");
219 return retval;
220 }
221
222 /* Read the thread name */
223 retval =
224 target_read_buffer(rtos->target,
225 name_ptr,
226 ECOS_THREAD_NAME_STR_SIZE,
227 (uint8_t *)&tmp_str);
228 if (retval != ERROR_OK) {
229 LOG_ERROR("Error reading thread name from eCos target");
230 return retval;
231 }
232 tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
233
234 if (tmp_str[0] == '\x00')
235 strcpy(tmp_str, "No Name");
236
237 rtos->thread_details[tasks_found].thread_name_str =
238 malloc(strlen(tmp_str)+1);
239 strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
240
241 /* Read the thread status */
242 int64_t thread_status = 0;
243 retval = target_read_buffer(rtos->target,
244 thread_index + param->thread_state_offset,
245 4,
246 (uint8_t *)&thread_status);
247 if (retval != ERROR_OK) {
248 LOG_ERROR("Error reading thread state from eCos target");
249 return retval;
250 }
251
252 for (i = 0; (i < ECOS_NUM_STATES) && (eCos_thread_states[i].value != thread_status); i++) {
253 /*
254 * empty
255 */
256 }
257
258 const char *state_desc;
259 if (i < ECOS_NUM_STATES)
260 state_desc = eCos_thread_states[i].desc;
261 else
262 state_desc = "Unknown state";
263
264 rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
265 state_desc)+1);
266 strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc);
267
268 rtos->thread_details[tasks_found].exists = true;
269
270 rtos->thread_details[tasks_found].display_str = NULL;
271
272 tasks_found++;
273 prev_thread_ptr = thread_index;
274
275 /* Get the location of the next thread structure. */
276 thread_index = rtos->symbols[eCos_VAL_thread_list].address;
277 retval = target_read_buffer(rtos->target,
278 prev_thread_ptr + param->thread_next_offset,
279 param->pointer_width,
280 (uint8_t *) &thread_index);
281 if (retval != ERROR_OK) {
282 LOG_ERROR("Error reading next thread pointer in eCos thread list");
283 return retval;
284 }
285 } while (thread_index != first_thread);
286
287 rtos->thread_count = tasks_found;
288 return 0;
289 }
290
291 static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
292 {
293 int retval;
294 const struct eCos_params *param;
295
296 *hex_reg_list = NULL;
297
298 if (rtos == NULL)
299 return -1;
300
301 if (thread_id == 0)
302 return -2;
303
304 if (rtos->rtos_specific_params == NULL)
305 return -3;
306
307 param = (const struct eCos_params *) rtos->rtos_specific_params;
308
309 /* Find the thread with that thread id */
310 uint16_t id = 0;
311 uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address;
312 uint32_t thread_index;
313 target_read_buffer(rtos->target, thread_list_head, param->pointer_width,
314 (uint8_t *)&thread_index);
315 bool done = false;
316 while (!done) {
317 retval = target_read_buffer(rtos->target,
318 thread_index + param->thread_uniqueid_offset,
319 2,
320 (uint8_t *)&id);
321 if (retval != ERROR_OK) {
322 LOG_ERROR("Error reading unique id from eCos thread");
323 return retval;
324 }
325
326 if (id == thread_id) {
327 done = true;
328 break;
329 }
330 target_read_buffer(rtos->target,
331 thread_index + param->thread_next_offset,
332 param->pointer_width,
333 (uint8_t *) &thread_index);
334 }
335
336 if (done) {
337 /* Read the stack pointer */
338 int64_t stack_ptr = 0;
339 retval = target_read_buffer(rtos->target,
340 thread_index + param->thread_stack_offset,
341 param->pointer_width,
342 (uint8_t *)&stack_ptr);
343 if (retval != ERROR_OK) {
344 LOG_ERROR("Error reading stack frame from eCos thread");
345 return retval;
346 }
347
348 return rtos_generic_stack_read(rtos->target,
349 param->stacking_info,
350 stack_ptr,
351 hex_reg_list);
352 }
353
354 return -1;
355 }
356
357 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
358 {
359 unsigned int i;
360 *symbol_list = calloc(
361 ARRAY_SIZE(eCos_symbol_list), sizeof(symbol_table_elem_t));
362
363 for (i = 0; i < ARRAY_SIZE(eCos_symbol_list); i++)
364 (*symbol_list)[i].symbol_name = eCos_symbol_list[i];
365
366 return 0;
367 }
368
369 static int eCos_detect_rtos(struct target *target)
370 {
371 if ((target->rtos->symbols != NULL) &&
372 (target->rtos->symbols[eCos_VAL_thread_list].address != 0)) {
373 /* looks like eCos */
374 return 1;
375 }
376 return 0;
377 }
378
379 static int eCos_create(struct target *target)
380 {
381 int i = 0;
382 while ((i < ECOS_NUM_PARAMS) &&
383 (0 != strcmp(eCos_params_list[i].target_name, target->type->name))) {
384 i++;
385 }
386 if (i >= ECOS_NUM_PARAMS) {
387 LOG_ERROR("Could not find target in eCos compatibility list");
388 return -1;
389 }
390
391 target->rtos->rtos_specific_params = (void *) &eCos_params_list[i];
392 target->rtos->current_thread = 0;
393 target->rtos->thread_details = NULL;
394 return 0;
395 }

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)