ecos: add missing error propagation
[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 {
39 int value;
40 char * desc;
41 };
42
43
44 struct eCos_thread_state eCos_thread_states[] =
45 {
46 { 0, "Ready" },
47 { 1, "Sleeping" },
48 { 2, "Countsleep" },
49 { 4, "Suspended" },
50 { 8, "Creating" },
51 { 16, "Exited" }
52 };
53
54 #define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state))
55
56 struct eCos_params
57 {
58 char * target_name;
59 unsigned char pointer_width;
60 unsigned char thread_stack_offset;
61 unsigned char thread_name_offset;
62 unsigned char thread_state_offset;
63 unsigned char thread_next_offset;
64 unsigned char thread_uniqueid_offset;
65 const struct rtos_register_stacking* stacking_info;
66 };
67
68 const struct eCos_params eCos_params_list[] =
69 {
70 { "cortex_m3", // target_name
71 4, // pointer_width;
72 0x0c, // thread_stack_offset;
73 0x9c, // thread_name_offset;
74 0x3c, // thread_state_offset;
75 0xa0, // thread_next_offset
76 0x4c, // thread_uniqueid_offset
77 &rtos_eCos_Cortex_M3_stacking // stacking_info
78 }
79
80 };
81
82 #define ECOS_NUM_PARAMS ((int)(sizeof(eCos_params_list)/sizeof(struct eCos_params)))
83
84 enum eCos_symbol_values
85 {
86 eCos_VAL_thread_list = 0,
87 eCos_VAL_current_thread_ptr = 1
88 };
89
90 static char* eCos_symbol_list[] =
91 {
92 "Cyg_Thread::thread_list",
93 "Cyg_Scheduler_Base::current_thread",
94 NULL
95 };
96
97
98
99 #define ECOS_NUM_SYMBOLS (sizeof(eCos_symbol_list)/sizeof(char*))
100
101
102 const struct rtos_type eCos_rtos =
103 {
104 .name = "eCos",
105
106 .detect_rtos = eCos_detect_rtos,
107 .create = eCos_create,
108 .update_threads = eCos_update_threads,
109 .get_thread_reg_list = eCos_get_thread_reg_list,
110 .get_symbol_list_to_lookup = eCos_get_symbol_list_to_lookup,
111
112 };
113
114 static int eCos_update_threads( struct rtos* rtos)
115 {
116 int retval;
117 int tasks_found = 0;
118 int thread_list_size = 0;
119 const struct eCos_params* param;
120
121 if ( rtos == NULL )
122 {
123 return -1;
124 }
125
126 if (rtos->rtos_specific_params == NULL )
127 {
128 return -3;
129 }
130
131 param = (const struct eCos_params*) rtos->rtos_specific_params;
132
133 if ( rtos->symbols == NULL )
134 {
135 LOG_OUTPUT("No symbols for eCos\r\n");
136 return -4;
137 }
138
139 if ( rtos->symbols[eCos_VAL_thread_list].address == 0 )
140 {
141 LOG_OUTPUT("Don't have the thread list head\r\n");
142 return -2;
143 }
144
145
146 // wipe out previous thread details if any
147 if ( rtos->thread_details != NULL )
148 {
149 int j;
150 for( j = 0; j < rtos->thread_count; j++ )
151 {
152 if ( rtos->thread_details[j].display_str != NULL )
153 {
154 free( rtos->thread_details[j].display_str );
155 rtos->thread_details[j].display_str = NULL;
156 }
157 if ( rtos->thread_details[j].thread_name_str != NULL )
158 {
159 free( rtos->thread_details[j].thread_name_str );
160 rtos->thread_details[j].thread_name_str = NULL;
161 }
162 if ( rtos->thread_details[j].extra_info_str != NULL )
163 {
164 free( rtos->thread_details[j].extra_info_str );
165 rtos->thread_details[j].extra_info_str = NULL;
166 }
167 }
168 free( rtos->thread_details );
169 rtos->thread_details = NULL;
170 }
171
172
173 // determine the number of current threads
174 uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address;
175 uint32_t thread_index;
176 target_read_buffer( rtos->target, thread_list_head, param->pointer_width, (uint8_t *) &thread_index );
177 uint32_t first_thread = thread_index;
178 do
179 {
180 thread_list_size++;
181 retval = target_read_buffer( rtos->target, thread_index + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_index );
182 if (retval != ERROR_OK)
183 return retval;
184 } while( thread_index!=first_thread );
185
186 // read the current thread id
187 uint32_t current_thread_addr;
188 retval = target_read_buffer( rtos->target, rtos->symbols[eCos_VAL_current_thread_ptr].address, 4, (uint8_t *)&current_thread_addr);
189 if (retval != ERROR_OK)
190 return retval;
191 rtos->current_thread = 0;
192 retval = target_read_buffer( rtos->target, current_thread_addr + param->thread_uniqueid_offset, 2, (uint8_t *)&rtos->current_thread);
193 if ( retval != ERROR_OK )
194 {
195 LOG_OUTPUT("Could not read eCos current thread from target\r\n");
196 return retval;
197 }
198
199 if ( ( thread_list_size == 0 ) || ( rtos->current_thread == 0 ) )
200 {
201 // Either : No RTOS threads - there is always at least the current execution though
202 // OR : No current thread - all threads suspended - show the current execution of idling
203 char tmp_str[] = "Current Execution";
204 thread_list_size++;
205 tasks_found++;
206 rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
207 rtos->thread_details->threadid = 1;
208 rtos->thread_details->exists = true;
209 rtos->thread_details->display_str = NULL;
210 rtos->thread_details->extra_info_str = NULL;
211 rtos->thread_details->thread_name_str = (char*) malloc( sizeof(tmp_str) );
212 strcpy( rtos->thread_details->thread_name_str, tmp_str );
213
214
215 if ( thread_list_size == 0 )
216 {
217 rtos->thread_count = 1;
218 return ERROR_OK;
219 }
220 }
221 else
222 {
223 // create space for new thread details
224 rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
225 }
226
227 // loop over all threads
228 thread_index = first_thread;
229 do
230 {
231
232 #define ECOS_THREAD_NAME_STR_SIZE (200)
233 char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
234 unsigned int i = 0;
235 uint32_t name_ptr = 0;
236 uint32_t prev_thread_ptr;
237
238 // Save the thread pointer
239 uint16_t thread_id;
240 retval = target_read_buffer( rtos->target, thread_index + param->thread_uniqueid_offset, 2, (uint8_t *)&thread_id);
241 if ( retval != ERROR_OK )
242 {
243 LOG_OUTPUT("Could not read eCos thread id from target\r\n");
244 return retval;
245 }
246 rtos->thread_details[tasks_found].threadid = thread_id;
247
248 // read the name pointer
249 retval = target_read_buffer( rtos->target, thread_index + param->thread_name_offset, param->pointer_width, (uint8_t *)&name_ptr);
250 if ( retval != ERROR_OK )
251 {
252 LOG_OUTPUT("Could not read eCos thread name pointer from target\r\n");
253 return retval;
254 }
255
256 // Read the thread name
257 retval = target_read_buffer( rtos->target, name_ptr, ECOS_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str);
258 if ( retval != ERROR_OK )
259 {
260 LOG_OUTPUT("Error reading thread name from eCos target\r\n");
261 return retval;
262 }
263 tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
264
265 if ( tmp_str[0] == '\x00' )
266 {
267 strcpy(tmp_str,"No Name");
268 }
269
270 rtos->thread_details[tasks_found].thread_name_str = (char*)malloc( strlen(tmp_str)+1 );
271 strcpy( rtos->thread_details[tasks_found].thread_name_str, tmp_str );
272
273 // Read the thread status
274 int64_t thread_status = 0;
275 retval = target_read_buffer( rtos->target, thread_index + param->thread_state_offset, 4, (uint8_t *)&thread_status);
276 if ( retval != ERROR_OK )
277 {
278 LOG_OUTPUT("Error reading thread state from eCos target\r\n");
279 return retval;
280 }
281
282 for( i = 0; (i < ECOS_NUM_STATES) && (eCos_thread_states[i].value!=thread_status); i++ )
283 {
284 }
285
286 char * state_desc;
287 if (i < ECOS_NUM_STATES)
288 {
289 state_desc = eCos_thread_states[i].desc;
290 }
291 else
292 {
293 state_desc = "Unknown state";
294 }
295
296 rtos->thread_details[tasks_found].extra_info_str = (char*)malloc( strlen(state_desc)+1 );
297 strcpy( rtos->thread_details[tasks_found].extra_info_str, state_desc );
298
299 rtos->thread_details[tasks_found].exists = true;
300
301 rtos->thread_details[tasks_found].display_str = NULL;
302
303
304 tasks_found++;
305 prev_thread_ptr = thread_index;
306
307 // Get the location of the next thread structure.
308 thread_index = rtos->symbols[eCos_VAL_thread_list].address;
309 retval = target_read_buffer( rtos->target, prev_thread_ptr + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_index );
310 if ( retval != ERROR_OK )
311 {
312 LOG_OUTPUT("Error reading next thread pointer in eCos thread list\r\n");
313 return retval;
314 }
315 }
316 while( thread_index!=first_thread );
317
318 rtos->thread_count = tasks_found;
319 return 0;
320 }
321
322 static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char ** hex_reg_list )
323 {
324
325 int retval;
326 const struct eCos_params* param;
327
328 *hex_reg_list = NULL;
329
330 if ( rtos == NULL )
331 {
332 return -1;
333 }
334
335 if ( thread_id == 0 )
336 {
337 return -2;
338 }
339
340 if (rtos->rtos_specific_params == NULL )
341 {
342 return -3;
343 }
344
345 param = (const struct eCos_params*) rtos->rtos_specific_params;
346
347
348 // Find the thread with that thread id
349 uint16_t id=0;
350 uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address;
351 uint32_t thread_index;
352 target_read_buffer( rtos->target, thread_list_head, param->pointer_width, (uint8_t *) &thread_index );
353 bool done=false;
354 while(!done)
355 {
356 retval = target_read_buffer( rtos->target, thread_index + param->thread_uniqueid_offset, 2, (uint8_t*)&id);
357 if ( retval != ERROR_OK )
358 {
359 LOG_OUTPUT("Error reading unique id from eCos thread\r\n");
360 return retval;
361 }
362
363 if( id==thread_id )
364 {
365 done=true;
366 break;
367 }
368 target_read_buffer( rtos->target, thread_index + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_index );
369 }
370
371 if(done)
372 {
373 // Read the stack pointer
374 int64_t stack_ptr = 0;
375 retval = target_read_buffer( rtos->target, thread_index + param->thread_stack_offset, param->pointer_width, (uint8_t*)&stack_ptr);
376 if ( retval != ERROR_OK )
377 {
378 LOG_OUTPUT("Error reading stack frame from eCos thread\r\n");
379 return retval;
380 }
381
382 return rtos_generic_stack_read( rtos->target, param->stacking_info, stack_ptr, hex_reg_list );
383 }
384
385 return -1;
386 }
387
388
389
390 static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_list[])
391 {
392 unsigned int i;
393 *symbol_list = (symbol_table_elem_t *) malloc( sizeof( symbol_table_elem_t ) * ECOS_NUM_SYMBOLS );
394
395 for( i = 0; i < ECOS_NUM_SYMBOLS; i++ )
396 {
397 (*symbol_list)[i].symbol_name = eCos_symbol_list[i];
398 }
399
400 return 0;
401 }
402
403 static int eCos_detect_rtos( struct target* target )
404 {
405 if ( ( target->rtos->symbols != NULL ) &&
406 ( target->rtos->symbols[eCos_VAL_thread_list].address != 0 ) )
407 {
408 // looks like eCos
409 return 1;
410 }
411 return 0;
412 }
413
414 static int eCos_create( struct target* target )
415 {
416 int i = 0;
417 while ( ( i < ECOS_NUM_PARAMS ) && ( 0 != strcmp( eCos_params_list[i].target_name, target->type->name ) ) )
418 {
419 i++;
420 }
421 if ( i >= ECOS_NUM_PARAMS )
422 {
423 LOG_OUTPUT("Could not find target in eCos compatibility list\r\n");
424 return -1;
425 }
426
427 target->rtos->rtos_specific_params = (void*) &eCos_params_list[i];
428 target->rtos->current_thread = 0;
429 target->rtos->thread_details = NULL;
430 return 0;
431 }

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)