rtos: constify symbol names and lists
[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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 const char *desc;
41 };
42
43 static const 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 const 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 static const struct eCos_params eCos_params_list[] = {
66 {
67 "cortex_m", /* 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 const char * const 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_ERROR("No symbols for eCos");
119 return -4;
120 }
121
122 if (rtos->symbols[eCos_VAL_thread_list].address == 0) {
123 LOG_ERROR("Don't have the thread list head");
124 return -2;
125 }
126
127 /* wipe out previous thread details if any */
128 rtos_free_threadlist(rtos);
129
130 /* determine the number of current threads */
131 uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address;
132 uint32_t thread_index;
133 target_read_buffer(rtos->target,
134 thread_list_head,
135 param->pointer_width,
136 (uint8_t *) &thread_index);
137 uint32_t first_thread = thread_index;
138 do {
139 thread_list_size++;
140 retval = target_read_buffer(rtos->target,
141 thread_index + param->thread_next_offset,
142 param->pointer_width,
143 (uint8_t *) &thread_index);
144 if (retval != ERROR_OK)
145 return retval;
146 } while (thread_index != first_thread);
147
148 /* read the current thread id */
149 uint32_t current_thread_addr;
150 retval = target_read_buffer(rtos->target,
151 rtos->symbols[eCos_VAL_current_thread_ptr].address,
152 4,
153 (uint8_t *)&current_thread_addr);
154 if (retval != ERROR_OK)
155 return retval;
156 rtos->current_thread = 0;
157 retval = target_read_buffer(rtos->target,
158 current_thread_addr + param->thread_uniqueid_offset,
159 2,
160 (uint8_t *)&rtos->current_thread);
161 if (retval != ERROR_OK) {
162 LOG_ERROR("Could not read eCos current thread from target");
163 return retval;
164 }
165
166 if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
167 /* Either : No RTOS threads - there is always at least the current execution though */
168 /* OR : No current thread - all threads suspended - show the current execution
169 * of idling */
170 char tmp_str[] = "Current Execution";
171 thread_list_size++;
172 tasks_found++;
173 rtos->thread_details = malloc(
174 sizeof(struct thread_detail) * thread_list_size);
175 rtos->thread_details->threadid = 1;
176 rtos->thread_details->exists = true;
177 rtos->thread_details->display_str = NULL;
178 rtos->thread_details->extra_info_str = NULL;
179 rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
180 strcpy(rtos->thread_details->thread_name_str, tmp_str);
181
182 if (thread_list_size == 0) {
183 rtos->thread_count = 1;
184 return ERROR_OK;
185 }
186 } else {
187 /* create space for new thread details */
188 rtos->thread_details = malloc(
189 sizeof(struct thread_detail) * thread_list_size);
190 }
191
192 /* loop over all threads */
193 thread_index = first_thread;
194 do {
195
196 #define ECOS_THREAD_NAME_STR_SIZE (200)
197 char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
198 unsigned int i = 0;
199 uint32_t name_ptr = 0;
200 uint32_t prev_thread_ptr;
201
202 /* Save the thread pointer */
203 uint16_t thread_id;
204 retval = target_read_buffer(rtos->target,
205 thread_index + param->thread_uniqueid_offset,
206 2,
207 (uint8_t *)&thread_id);
208 if (retval != ERROR_OK) {
209 LOG_ERROR("Could not read eCos thread id from target");
210 return retval;
211 }
212 rtos->thread_details[tasks_found].threadid = thread_id;
213
214 /* read the name pointer */
215 retval = target_read_buffer(rtos->target,
216 thread_index + param->thread_name_offset,
217 param->pointer_width,
218 (uint8_t *)&name_ptr);
219 if (retval != ERROR_OK) {
220 LOG_ERROR("Could not read eCos thread name pointer from target");
221 return retval;
222 }
223
224 /* Read the thread name */
225 retval =
226 target_read_buffer(rtos->target,
227 name_ptr,
228 ECOS_THREAD_NAME_STR_SIZE,
229 (uint8_t *)&tmp_str);
230 if (retval != ERROR_OK) {
231 LOG_ERROR("Error reading thread name from eCos target");
232 return retval;
233 }
234 tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
235
236 if (tmp_str[0] == '\x00')
237 strcpy(tmp_str, "No Name");
238
239 rtos->thread_details[tasks_found].thread_name_str =
240 malloc(strlen(tmp_str)+1);
241 strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
242
243 /* Read the thread status */
244 int64_t thread_status = 0;
245 retval = target_read_buffer(rtos->target,
246 thread_index + param->thread_state_offset,
247 4,
248 (uint8_t *)&thread_status);
249 if (retval != ERROR_OK) {
250 LOG_ERROR("Error reading thread state from eCos target");
251 return retval;
252 }
253
254 for (i = 0; (i < ECOS_NUM_STATES) && (eCos_thread_states[i].value != thread_status); i++) {
255 /*
256 * empty
257 */
258 }
259
260 const char *state_desc;
261 if (i < ECOS_NUM_STATES)
262 state_desc = eCos_thread_states[i].desc;
263 else
264 state_desc = "Unknown state";
265
266 rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
267 state_desc)+1);
268 strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc);
269
270 rtos->thread_details[tasks_found].exists = true;
271
272 rtos->thread_details[tasks_found].display_str = NULL;
273
274 tasks_found++;
275 prev_thread_ptr = thread_index;
276
277 /* Get the location of the next thread structure. */
278 thread_index = rtos->symbols[eCos_VAL_thread_list].address;
279 retval = target_read_buffer(rtos->target,
280 prev_thread_ptr + param->thread_next_offset,
281 param->pointer_width,
282 (uint8_t *) &thread_index);
283 if (retval != ERROR_OK) {
284 LOG_ERROR("Error reading next thread pointer in eCos thread list");
285 return retval;
286 }
287 } while (thread_index != first_thread);
288
289 rtos->thread_count = tasks_found;
290 return 0;
291 }
292
293 static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
294 {
295 int retval;
296 const struct eCos_params *param;
297
298 *hex_reg_list = NULL;
299
300 if (rtos == NULL)
301 return -1;
302
303 if (thread_id == 0)
304 return -2;
305
306 if (rtos->rtos_specific_params == NULL)
307 return -3;
308
309 param = (const struct eCos_params *) rtos->rtos_specific_params;
310
311 /* Find the thread with that thread id */
312 uint16_t id = 0;
313 uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address;
314 uint32_t thread_index;
315 target_read_buffer(rtos->target, thread_list_head, param->pointer_width,
316 (uint8_t *)&thread_index);
317 bool done = false;
318 while (!done) {
319 retval = target_read_buffer(rtos->target,
320 thread_index + param->thread_uniqueid_offset,
321 2,
322 (uint8_t *)&id);
323 if (retval != ERROR_OK) {
324 LOG_ERROR("Error reading unique id from eCos thread");
325 return retval;
326 }
327
328 if (id == thread_id) {
329 done = true;
330 break;
331 }
332 target_read_buffer(rtos->target,
333 thread_index + param->thread_next_offset,
334 param->pointer_width,
335 (uint8_t *) &thread_index);
336 }
337
338 if (done) {
339 /* Read the stack pointer */
340 int64_t stack_ptr = 0;
341 retval = target_read_buffer(rtos->target,
342 thread_index + param->thread_stack_offset,
343 param->pointer_width,
344 (uint8_t *)&stack_ptr);
345 if (retval != ERROR_OK) {
346 LOG_ERROR("Error reading stack frame from eCos thread");
347 return retval;
348 }
349
350 return rtos_generic_stack_read(rtos->target,
351 param->stacking_info,
352 stack_ptr,
353 hex_reg_list);
354 }
355
356 return -1;
357 }
358
359 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
360 {
361 unsigned int i;
362 *symbol_list = malloc(
363 sizeof(symbol_table_elem_t) * ARRAY_SIZE(eCos_symbol_list));
364
365 for (i = 0; i < ARRAY_SIZE(eCos_symbol_list); i++)
366 (*symbol_list)[i].symbol_name = eCos_symbol_list[i];
367
368 return 0;
369 }
370
371 static int eCos_detect_rtos(struct target *target)
372 {
373 if ((target->rtos->symbols != NULL) &&
374 (target->rtos->symbols[eCos_VAL_thread_list].address != 0)) {
375 /* looks like eCos */
376 return 1;
377 }
378 return 0;
379 }
380
381 static int eCos_create(struct target *target)
382 {
383 int i = 0;
384 while ((i < ECOS_NUM_PARAMS) &&
385 (0 != strcmp(eCos_params_list[i].target_name, target->type->name))) {
386 i++;
387 }
388 if (i >= ECOS_NUM_PARAMS) {
389 LOG_ERROR("Could not find target in eCos compatibility list");
390 return -1;
391 }
392
393 target->rtos->rtos_specific_params = (void *) &eCos_params_list[i];
394 target->rtos->current_thread = 0;
395 target->rtos->thread_details = NULL;
396 return 0;
397 }

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)