rtos: support gdb_get_register_packet
[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 bool 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, struct rtos_reg **reg_list, int *num_regs);
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->extra_info_str = NULL;
176 rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
177 strcpy(rtos->thread_details->thread_name_str, tmp_str);
178
179 if (thread_list_size == 0) {
180 rtos->thread_count = 1;
181 return ERROR_OK;
182 }
183 } else {
184 /* create space for new thread details */
185 rtos->thread_details = malloc(
186 sizeof(struct thread_detail) * thread_list_size);
187 }
188
189 /* loop over all threads */
190 thread_index = first_thread;
191 do {
192
193 #define ECOS_THREAD_NAME_STR_SIZE (200)
194 char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
195 unsigned int i = 0;
196 uint32_t name_ptr = 0;
197 uint32_t prev_thread_ptr;
198
199 /* Save the thread pointer */
200 uint16_t thread_id;
201 retval = target_read_buffer(rtos->target,
202 thread_index + param->thread_uniqueid_offset,
203 2,
204 (uint8_t *)&thread_id);
205 if (retval != ERROR_OK) {
206 LOG_ERROR("Could not read eCos thread id from target");
207 return retval;
208 }
209 rtos->thread_details[tasks_found].threadid = thread_id;
210
211 /* read the name pointer */
212 retval = target_read_buffer(rtos->target,
213 thread_index + param->thread_name_offset,
214 param->pointer_width,
215 (uint8_t *)&name_ptr);
216 if (retval != ERROR_OK) {
217 LOG_ERROR("Could not read eCos thread name pointer from target");
218 return retval;
219 }
220
221 /* Read the thread name */
222 retval =
223 target_read_buffer(rtos->target,
224 name_ptr,
225 ECOS_THREAD_NAME_STR_SIZE,
226 (uint8_t *)&tmp_str);
227 if (retval != ERROR_OK) {
228 LOG_ERROR("Error reading thread name from eCos target");
229 return retval;
230 }
231 tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
232
233 if (tmp_str[0] == '\x00')
234 strcpy(tmp_str, "No Name");
235
236 rtos->thread_details[tasks_found].thread_name_str =
237 malloc(strlen(tmp_str)+1);
238 strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
239
240 /* Read the thread status */
241 int64_t thread_status = 0;
242 retval = target_read_buffer(rtos->target,
243 thread_index + param->thread_state_offset,
244 4,
245 (uint8_t *)&thread_status);
246 if (retval != ERROR_OK) {
247 LOG_ERROR("Error reading thread state from eCos target");
248 return retval;
249 }
250
251 for (i = 0; (i < ECOS_NUM_STATES) && (eCos_thread_states[i].value != thread_status); i++) {
252 /*
253 * empty
254 */
255 }
256
257 const char *state_desc;
258 if (i < ECOS_NUM_STATES)
259 state_desc = eCos_thread_states[i].desc;
260 else
261 state_desc = "Unknown state";
262
263 rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
264 state_desc)+8);
265 sprintf(rtos->thread_details[tasks_found].extra_info_str, "State: %s", state_desc);
266
267 rtos->thread_details[tasks_found].exists = true;
268
269 tasks_found++;
270 prev_thread_ptr = thread_index;
271
272 /* Get the location of the next thread structure. */
273 thread_index = rtos->symbols[eCos_VAL_thread_list].address;
274 retval = target_read_buffer(rtos->target,
275 prev_thread_ptr + param->thread_next_offset,
276 param->pointer_width,
277 (uint8_t *) &thread_index);
278 if (retval != ERROR_OK) {
279 LOG_ERROR("Error reading next thread pointer in eCos thread list");
280 return retval;
281 }
282 } while (thread_index != first_thread);
283
284 rtos->thread_count = tasks_found;
285 return 0;
286 }
287
288 static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
289 struct rtos_reg **reg_list, int *num_regs)
290 {
291 int retval;
292 const struct eCos_params *param;
293
294 if (rtos == NULL)
295 return -1;
296
297 if (thread_id == 0)
298 return -2;
299
300 if (rtos->rtos_specific_params == NULL)
301 return -3;
302
303 param = (const struct eCos_params *) rtos->rtos_specific_params;
304
305 /* Find the thread with that thread id */
306 uint16_t id = 0;
307 uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address;
308 uint32_t thread_index;
309 target_read_buffer(rtos->target, thread_list_head, param->pointer_width,
310 (uint8_t *)&thread_index);
311 bool done = false;
312 while (!done) {
313 retval = target_read_buffer(rtos->target,
314 thread_index + param->thread_uniqueid_offset,
315 2,
316 (uint8_t *)&id);
317 if (retval != ERROR_OK) {
318 LOG_ERROR("Error reading unique id from eCos thread");
319 return retval;
320 }
321
322 if (id == thread_id) {
323 done = true;
324 break;
325 }
326 target_read_buffer(rtos->target,
327 thread_index + param->thread_next_offset,
328 param->pointer_width,
329 (uint8_t *) &thread_index);
330 }
331
332 if (done) {
333 /* Read the stack pointer */
334 int64_t stack_ptr = 0;
335 retval = target_read_buffer(rtos->target,
336 thread_index + param->thread_stack_offset,
337 param->pointer_width,
338 (uint8_t *)&stack_ptr);
339 if (retval != ERROR_OK) {
340 LOG_ERROR("Error reading stack frame from eCos thread");
341 return retval;
342 }
343
344 return rtos_generic_stack_read(rtos->target,
345 param->stacking_info,
346 stack_ptr,
347 reg_list,
348 num_regs);
349 }
350
351 return -1;
352 }
353
354 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
355 {
356 unsigned int i;
357 *symbol_list = calloc(
358 ARRAY_SIZE(eCos_symbol_list), sizeof(symbol_table_elem_t));
359
360 for (i = 0; i < ARRAY_SIZE(eCos_symbol_list); i++)
361 (*symbol_list)[i].symbol_name = eCos_symbol_list[i];
362
363 return 0;
364 }
365
366 static bool eCos_detect_rtos(struct target *target)
367 {
368 if ((target->rtos->symbols != NULL) &&
369 (target->rtos->symbols[eCos_VAL_thread_list].address != 0)) {
370 /* looks like eCos */
371 return true;
372 }
373 return false;
374 }
375
376 static int eCos_create(struct target *target)
377 {
378 int i = 0;
379 while ((i < ECOS_NUM_PARAMS) &&
380 (0 != strcmp(eCos_params_list[i].target_name, target->type->name))) {
381 i++;
382 }
383 if (i >= ECOS_NUM_PARAMS) {
384 LOG_ERROR("Could not find target in eCos compatibility list");
385 return -1;
386 }
387
388 target->rtos->rtos_specific_params = (void *) &eCos_params_list[i];
389 target->rtos->current_thread = 0;
390 target->rtos->thread_details = NULL;
391 return 0;
392 }

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)