OpenOCD
eCos.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  ***************************************************************************/
5 
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9 
10 #include <helper/time_support.h>
11 #include <jtag/jtag.h>
12 #include "target/target.h"
13 #include "target/target_type.h"
14 #include "rtos.h"
15 #include "helper/log.h"
16 #include "helper/types.h"
17 #include "rtos_ecos_stackings.h"
18 
19 static bool ecos_detect_rtos(struct target *target);
20 static int ecos_create(struct target *target);
21 static int ecos_update_threads(struct rtos *rtos);
22 static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs);
23 static int ecos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
24 
26  int value;
27  const char *desc;
28 };
29 
30 static const struct ecos_thread_state ecos_thread_states[] = {
31  { 0, "Ready" },
32  { 1, "Sleeping" },
33  { 2, "Countsleep" },
34  { 4, "Suspended" },
35  { 8, "Creating" },
36  { 16, "Exited" }
37 };
38 
39 #define ECOS_NUM_STATES ARRAY_SIZE(ecos_thread_states)
40 
41 struct ecos_params {
42  const char *target_name;
43  unsigned char pointer_width;
44  unsigned char thread_stack_offset;
45  unsigned char thread_name_offset;
46  unsigned char thread_state_offset;
47  unsigned char thread_next_offset;
48  unsigned char thread_uniqueid_offset;
50 };
51 
52 static const struct ecos_params ecos_params_list[] = {
53  {
54  "cortex_m", /* target_name */
55  4, /* pointer_width; */
56  0x0c, /* thread_stack_offset; */
57  0x9c, /* thread_name_offset; */
58  0x3c, /* thread_state_offset; */
59  0xa0, /* thread_next_offset */
60  0x4c, /* thread_uniqueid_offset */
61  &rtos_ecos_cortex_m3_stacking /* stacking_info */
62  }
63 };
64 
68 };
69 
70 static const char * const ecos_symbol_list[] = {
71  "Cyg_Thread::thread_list",
72  "Cyg_Scheduler_Base::current_thread",
73  NULL
74 };
75 
76 const struct rtos_type ecos_rtos = {
77  .name = "eCos",
78 
79  .detect_rtos = ecos_detect_rtos,
80  .create = ecos_create,
81  .update_threads = ecos_update_threads,
82  .get_thread_reg_list = ecos_get_thread_reg_list,
83  .get_symbol_list_to_lookup = ecos_get_symbol_list_to_lookup,
84 
85 };
86 
87 static int ecos_update_threads(struct rtos *rtos)
88 {
89  int retval;
90  int tasks_found = 0;
91  int thread_list_size = 0;
92  const struct ecos_params *param;
93 
94  if (!rtos)
95  return -1;
96 
98  return -3;
99 
100  param = (const struct ecos_params *) rtos->rtos_specific_params;
101 
102  if (!rtos->symbols) {
103  LOG_ERROR("No symbols for eCos");
104  return -4;
105  }
106 
108  LOG_ERROR("Don't have the thread list head");
109  return -2;
110  }
111 
112  /* wipe out previous thread details if any */
114 
115  /* determine the number of current threads */
116  uint32_t thread_list_head = rtos->symbols[ECOS_VAL_THREAD_LIST].address;
117  uint32_t thread_index;
119  thread_list_head,
120  param->pointer_width,
121  (uint8_t *) &thread_index);
122  uint32_t first_thread = thread_index;
123  do {
124  thread_list_size++;
125  retval = target_read_buffer(rtos->target,
126  thread_index + param->thread_next_offset,
127  param->pointer_width,
128  (uint8_t *) &thread_index);
129  if (retval != ERROR_OK)
130  return retval;
131  } while (thread_index != first_thread);
132 
133  /* read the current thread id */
134  uint32_t current_thread_addr;
135  retval = target_read_buffer(rtos->target,
137  4,
138  (uint8_t *)&current_thread_addr);
139  if (retval != ERROR_OK)
140  return retval;
141  rtos->current_thread = 0;
142  retval = target_read_buffer(rtos->target,
143  current_thread_addr + param->thread_uniqueid_offset,
144  2,
145  (uint8_t *)&rtos->current_thread);
146  if (retval != ERROR_OK) {
147  LOG_ERROR("Could not read eCos current thread from target");
148  return retval;
149  }
150 
151  if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
152  /* Either : No RTOS threads - there is always at least the current execution though */
153  /* OR : No current thread - all threads suspended - show the current execution
154  * of idling */
155  char tmp_str[] = "Current Execution";
156  thread_list_size++;
157  tasks_found++;
158  rtos->thread_details = malloc(
159  sizeof(struct thread_detail) * thread_list_size);
161  rtos->thread_details->exists = true;
163  rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
164  strcpy(rtos->thread_details->thread_name_str, tmp_str);
165 
166  if (thread_list_size == 0) {
167  rtos->thread_count = 1;
168  return ERROR_OK;
169  }
170  } else {
171  /* create space for new thread details */
172  rtos->thread_details = malloc(
173  sizeof(struct thread_detail) * thread_list_size);
174  }
175 
176  /* loop over all threads */
177  thread_index = first_thread;
178  do {
179 
180  #define ECOS_THREAD_NAME_STR_SIZE (200)
181  char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
182  unsigned int i = 0;
183  uint32_t name_ptr = 0;
184  uint32_t prev_thread_ptr;
185 
186  /* Save the thread pointer */
187  uint16_t thread_id;
188  retval = target_read_buffer(rtos->target,
189  thread_index + param->thread_uniqueid_offset,
190  2,
191  (uint8_t *)&thread_id);
192  if (retval != ERROR_OK) {
193  LOG_ERROR("Could not read eCos thread id from target");
194  return retval;
195  }
196  rtos->thread_details[tasks_found].threadid = thread_id;
197 
198  /* read the name pointer */
199  retval = target_read_buffer(rtos->target,
200  thread_index + param->thread_name_offset,
201  param->pointer_width,
202  (uint8_t *)&name_ptr);
203  if (retval != ERROR_OK) {
204  LOG_ERROR("Could not read eCos thread name pointer from target");
205  return retval;
206  }
207 
208  /* Read the thread name */
209  retval =
211  name_ptr,
213  (uint8_t *)&tmp_str);
214  if (retval != ERROR_OK) {
215  LOG_ERROR("Error reading thread name from eCos target");
216  return retval;
217  }
218  tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
219 
220  if (tmp_str[0] == '\x00')
221  strcpy(tmp_str, "No Name");
222 
223  rtos->thread_details[tasks_found].thread_name_str =
224  malloc(strlen(tmp_str)+1);
225  strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
226 
227  /* Read the thread status */
228  int64_t thread_status = 0;
229  retval = target_read_buffer(rtos->target,
230  thread_index + param->thread_state_offset,
231  4,
232  (uint8_t *)&thread_status);
233  if (retval != ERROR_OK) {
234  LOG_ERROR("Error reading thread state from eCos target");
235  return retval;
236  }
237 
238  for (i = 0; (i < ECOS_NUM_STATES) && (ecos_thread_states[i].value != thread_status); i++) {
239  /*
240  * empty
241  */
242  }
243 
244  const char *state_desc;
245  if (i < ECOS_NUM_STATES)
246  state_desc = ecos_thread_states[i].desc;
247  else
248  state_desc = "Unknown state";
249 
250  rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
251  state_desc)+8);
252  sprintf(rtos->thread_details[tasks_found].extra_info_str, "State: %s", state_desc);
253 
254  rtos->thread_details[tasks_found].exists = true;
255 
256  tasks_found++;
257  prev_thread_ptr = thread_index;
258 
259  /* Get the location of the next thread structure. */
260  thread_index = rtos->symbols[ECOS_VAL_THREAD_LIST].address;
261  retval = target_read_buffer(rtos->target,
262  prev_thread_ptr + param->thread_next_offset,
263  param->pointer_width,
264  (uint8_t *) &thread_index);
265  if (retval != ERROR_OK) {
266  LOG_ERROR("Error reading next thread pointer in eCos thread list");
267  return retval;
268  }
269  } while (thread_index != first_thread);
270 
271  rtos->thread_count = tasks_found;
272  return 0;
273 }
274 
275 static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
276  struct rtos_reg **reg_list, int *num_regs)
277 {
278  int retval;
279  const struct ecos_params *param;
280 
281  if (!rtos)
282  return -1;
283 
284  if (thread_id == 0)
285  return -2;
286 
288  return -3;
289 
290  param = (const struct ecos_params *) rtos->rtos_specific_params;
291 
292  /* Find the thread with that thread id */
293  uint16_t id = 0;
294  uint32_t thread_list_head = rtos->symbols[ECOS_VAL_THREAD_LIST].address;
295  uint32_t thread_index;
296  target_read_buffer(rtos->target, thread_list_head, param->pointer_width,
297  (uint8_t *)&thread_index);
298  bool done = false;
299  while (!done) {
300  retval = target_read_buffer(rtos->target,
301  thread_index + param->thread_uniqueid_offset,
302  2,
303  (uint8_t *)&id);
304  if (retval != ERROR_OK) {
305  LOG_ERROR("Error reading unique id from eCos thread");
306  return retval;
307  }
308 
309  if (id == thread_id) {
310  done = true;
311  break;
312  }
314  thread_index + param->thread_next_offset,
315  param->pointer_width,
316  (uint8_t *) &thread_index);
317  }
318 
319  if (done) {
320  /* Read the stack pointer */
321  int64_t stack_ptr = 0;
322  retval = target_read_buffer(rtos->target,
323  thread_index + param->thread_stack_offset,
324  param->pointer_width,
325  (uint8_t *)&stack_ptr);
326  if (retval != ERROR_OK) {
327  LOG_ERROR("Error reading stack frame from eCos thread");
328  return retval;
329  }
330 
332  param->stacking_info,
333  stack_ptr,
334  reg_list,
335  num_regs);
336  }
337 
338  return -1;
339 }
340 
341 static int ecos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
342 {
343  unsigned int i;
344  *symbol_list = calloc(
346 
347  for (i = 0; i < ARRAY_SIZE(ecos_symbol_list); i++)
348  (*symbol_list)[i].symbol_name = ecos_symbol_list[i];
349 
350  return 0;
351 }
352 
353 static bool ecos_detect_rtos(struct target *target)
354 {
355  if ((target->rtos->symbols) &&
357  /* looks like eCos */
358  return true;
359  }
360  return false;
361 }
362 
363 static int ecos_create(struct target *target)
364 {
365  for (unsigned int i = 0; i < ARRAY_SIZE(ecos_params_list); i++)
366  if (strcmp(ecos_params_list[i].target_name, target->type->name) == 0) {
368  target->rtos->current_thread = 0;
370  return 0;
371  }
372 
373  LOG_ERROR("Could not find target in eCos compatibility list");
374  return -1;
375 }
static struct aice_port_param_s param
ecos_symbol_values
Definition: eCos.c:65
@ ECOS_VAL_THREAD_LIST
Definition: eCos.c:66
@ ECOS_VAL_CURRENT_THREAD_PTR
Definition: eCos.c:67
static const struct ecos_thread_state ecos_thread_states[]
Definition: eCos.c:30
static bool ecos_detect_rtos(struct target *target)
Definition: eCos.c:353
static int ecos_update_threads(struct rtos *rtos)
Definition: eCos.c:87
#define ECOS_THREAD_NAME_STR_SIZE
const struct rtos_type ecos_rtos
Definition: eCos.c:76
static const char *const ecos_symbol_list[]
Definition: eCos.c:70
static int ecos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
Definition: eCos.c:341
static int ecos_create(struct target *target)
Definition: eCos.c:363
static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs)
Definition: eCos.c:275
#define ECOS_NUM_STATES
Definition: eCos.c:39
static const struct ecos_params ecos_params_list[]
Definition: eCos.c:52
The JTAG interface can be implemented with a software or hardware fifo.
#define LOG_ERROR(expr ...)
Definition: log.h:123
#define ERROR_OK
Definition: log.h:155
int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, int64_t stack_ptr, struct rtos_reg **reg_list, int *num_regs)
Definition: rtos.c:617
void rtos_free_threadlist(struct rtos *rtos)
Definition: rtos.c:707
const struct rtos_register_stacking rtos_ecos_cortex_m3_stacking
const char * target_name
Definition: eCos.c:42
unsigned char thread_name_offset
Definition: eCos.c:45
const struct rtos_register_stacking * stacking_info
Definition: eCos.c:49
unsigned char thread_state_offset
Definition: eCos.c:46
unsigned char thread_next_offset
Definition: eCos.c:47
unsigned char thread_uniqueid_offset
Definition: eCos.c:48
unsigned char pointer_width
Definition: eCos.c:43
unsigned char thread_stack_offset
Definition: eCos.c:44
const char * desc
Definition: eCos.c:27
Definition: rtos.h:53
Definition: rtos.h:59
const char * name
Definition: rtos.h:60
Definition: rtos.h:36
int thread_count
Definition: rtos.h:47
struct thread_detail * thread_details
Definition: rtos.h:46
struct symbol_table_elem * symbols
Definition: rtos.h:39
struct target * target
Definition: rtos.h:40
void * rtos_specific_params
Definition: rtos.h:50
threadid_t current_thread
Definition: rtos.h:45
Table should be terminated by an element with NULL in symbol_name.
Definition: rtos.h:23
symbol_address_t address
Definition: rtos.h:25
const char * name
Name of this type of target.
Definition: target_type.h:31
Definition: target.h:120
struct rtos * rtos
Definition: target.h:188
struct target_type * type
Definition: target.h:121
char * extra_info_str
Definition: rtos.h:33
char * thread_name_str
Definition: rtos.h:32
bool exists
Definition: rtos.h:31
threadid_t threadid
Definition: rtos.h:30
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2473
static const char * target_name(struct target *target)
Returns the instance-specific name of the specified target.
Definition: target.h:234
#define ARRAY_SIZE(x)
Compute the number of elements of a variable length array.
Definition: types.h:57
#define NULL
Definition: usb.h:16