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

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)