OpenOCD
embKernel.c
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2011 by Broadcom Corporation *
3  * Evan Hunter - ehunter@broadcom.com *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
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"
31 
32 #define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64)
33 
34 static bool embKernel_detect_rtos(struct target *target);
35 static int embKernel_create(struct target *target);
36 static int embKernel_update_threads(struct rtos *rtos);
37 static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
39 
41  .name = "embKernel",
42  .detect_rtos = embKernel_detect_rtos,
43  .create = embKernel_create,
44  .update_threads = embKernel_update_threads,
45  .get_thread_reg_list =
47  .get_symbol_list_to_lookup = embKernel_get_symbol_list_to_lookup,
48 };
49 
50 enum {
57 };
58 
59 static const char * const embKernel_symbol_list[] = {
60  "Rtos::sCurrentTask",
61  "Rtos::sListReady",
62  "Rtos::sListSleep",
63  "Rtos::sListSuspended",
64  "Rtos::sMaxPriorities",
65  "Rtos::sCurrentTaskCount",
66  NULL };
67 
69  const char *target_name;
70  const unsigned char pointer_width;
71  const unsigned char thread_count_width;
72  const unsigned char rtos_list_size;
73  const unsigned char thread_stack_offset;
74  const unsigned char thread_name_offset;
75  const unsigned char thread_priority_offset;
76  const unsigned char thread_priority_width;
77  const unsigned char iterable_next_offset;
78  const unsigned char iterable_task_owner_offset;
80 };
81 
82 static const struct embKernel_params embKernel_params_list[] = {
83  {
84  "cortex_m", /* target_name */
85  4, /* pointer_width */
86  4, /* thread_count_width */
87  8, /*rtos_list_size */
88  0, /*thread_stack_offset */
89  4, /*thread_name_offset */
90  8, /*thread_priority_offset */
91  4, /*thread_priority_width */
92  4, /*iterable_next_offset */
93  12, /*iterable_task_owner_offset */
94  &rtos_embkernel_Cortex_M_stacking, /* stacking_info*/
95  },
96  { "hla_target", /* target_name */
97  4, /* pointer_width */
98  4, /* thread_count_width */
99  8, /*rtos_list_size */
100  0, /*thread_stack_offset */
101  4, /*thread_name_offset */
102  8, /*thread_priority_offset */
103  4, /*thread_priority_width */
104  4, /*iterable_next_offset */
105  12, /*iterable_task_owner_offset */
106  &rtos_embkernel_Cortex_M_stacking, /* stacking_info */
107  }
108 };
109 
110 static bool embKernel_detect_rtos(struct target *target)
111 {
112  if (target->rtos->symbols != NULL) {
113  if (target->rtos->symbols[SYMBOL_ID_sCurrentTask].address != 0)
114  return true;
115  }
116  return false;
117 }
118 
119 static int embKernel_create(struct target *target)
120 {
121  size_t i = 0;
122  while ((i < ARRAY_SIZE(embKernel_params_list)) &&
123  (0 != strcmp(embKernel_params_list[i].target_name, target->type->name)))
124  i++;
125 
126  if (i >= ARRAY_SIZE(embKernel_params_list)) {
127  LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
128  "list", target->type->name);
129  return -1;
130  }
131 
132  target->rtos->rtos_specific_params = (void *) &embKernel_params_list[i];
133  return 0;
134 }
135 
136 static int embKernel_get_tasks_details(struct rtos *rtos, int64_t iterable, const struct embKernel_params *param,
137  struct thread_detail *details, const char* state_str)
138 {
139  int64_t task = 0;
140  int retval = target_read_buffer(rtos->target, iterable + param->iterable_task_owner_offset, param->pointer_width,
141  (uint8_t *) &task);
142  if (retval != ERROR_OK)
143  return retval;
144  details->threadid = (threadid_t) task;
145  details->exists = true;
146 
147  int64_t name_ptr = 0;
148  retval = target_read_buffer(rtos->target, task + param->thread_name_offset, param->pointer_width,
149  (uint8_t *) &name_ptr);
150  if (retval != ERROR_OK)
151  return retval;
152 
154  if (name_ptr) {
156  (uint8_t *) details->thread_name_str);
157  if (retval != ERROR_OK)
158  return retval;
160  } else {
161  snprintf(details->thread_name_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "NoName:[0x%08X]", (unsigned int) task);
162  }
163 
164  int64_t priority = 0;
165  retval = target_read_buffer(rtos->target, task + param->thread_priority_offset, param->thread_priority_width,
166  (uint8_t *) &priority);
167  if (retval != ERROR_OK)
168  return retval;
170  if (task == rtos->current_thread) {
171  snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: Running, Priority: %u",
172  (unsigned int) priority);
173  } else {
174  snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: %s, Priority: %u",
175  state_str, (unsigned int) priority);
176  }
177 
178  LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable,
179  (unsigned int)task, details->thread_name_str);
180  return 0;
181 }
182 
183 static int embKernel_update_threads(struct rtos *rtos)
184 {
185  /* int i = 0; */
186  int retval;
187  const struct embKernel_params *param;
188 
189  if (rtos == NULL)
190  return -1;
191 
192  if (rtos->rtos_specific_params == NULL)
193  return -3;
194 
195  if (rtos->symbols == NULL) {
196  LOG_ERROR("No symbols for embKernel");
197  return -4;
198  }
199 
200  if (rtos->symbols[SYMBOL_ID_sCurrentTask].address == 0) {
201  LOG_ERROR("Don't have the thread list head");
202  return -2;
203  }
204 
205  /* wipe out previous thread details if any */
206  rtos_free_threadlist(rtos);
207 
208  param = (const struct embKernel_params *) rtos->rtos_specific_params;
209 
211  (uint8_t *) &rtos->current_thread);
212  if (retval != ERROR_OK) {
213  LOG_ERROR("Error reading current thread in embKernel thread list");
214  return retval;
215  }
216 
217  int64_t max_used_priority = 0;
219  (uint8_t *) &max_used_priority);
220  if (retval != ERROR_OK)
221  return retval;
222 
223  int thread_list_size = 0;
225  param->thread_count_width, (uint8_t *) &thread_list_size);
226 
227  if (retval != ERROR_OK) {
228  LOG_ERROR("Could not read embKernel thread count from target");
229  return retval;
230  }
231 
232  /* create space for new thread details */
233  rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size);
234  if (!rtos->thread_details) {
235  LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
236  return ERROR_FAIL;
237  }
238 
239  int threadIdx = 0;
240  /* Look for ready tasks */
241  for (int pri = 0; pri < max_used_priority; pri++) {
242  /* Get first item in queue */
243  int64_t iterable = 0;
244  retval = target_read_buffer(rtos->target,
245  rtos->symbols[SYMBOL_ID_sListReady].address + (pri * param->rtos_list_size), param->pointer_width,
246  (uint8_t *) &iterable);
247  if (retval != ERROR_OK)
248  return retval;
249  for (; iterable && threadIdx < thread_list_size; threadIdx++) {
250  /* Get info from this iterable item */
251  retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Ready");
252  if (retval != ERROR_OK)
253  return retval;
254  /* Get next iterable item */
255  retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
256  (uint8_t *) &iterable);
257  if (retval != ERROR_OK)
258  return retval;
259  }
260  }
261  /* Look for sleeping tasks */
262  int64_t iterable = 0;
264  (uint8_t *) &iterable);
265  if (retval != ERROR_OK)
266  return retval;
267  for (; iterable && threadIdx < thread_list_size; threadIdx++) {
268  /*Get info from this iterable item */
269  retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Sleeping");
270  if (retval != ERROR_OK)
271  return retval;
272  /*Get next iterable item */
273  retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
274  (uint8_t *) &iterable);
275  if (retval != ERROR_OK)
276  return retval;
277  }
278 
279  /* Look for suspended tasks */
280  iterable = 0;
282  (uint8_t *) &iterable);
283  if (retval != ERROR_OK)
284  return retval;
285  for (; iterable && threadIdx < thread_list_size; threadIdx++) {
286  /* Get info from this iterable item */
287  retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Suspended");
288  if (retval != ERROR_OK)
289  return retval;
290  /*Get next iterable item */
291  retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
292  (uint8_t *) &iterable);
293  if (retval != ERROR_OK)
294  return retval;
295  }
296 
297  rtos->thread_count = 0;
298  rtos->thread_count = threadIdx;
299  LOG_OUTPUT("Found %u tasks\n", (unsigned int)threadIdx);
300  return 0;
301 }
302 
303 static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
304 {
305  int retval;
306  const struct embKernel_params *param;
307  int64_t stack_ptr = 0;
308 
309  *hex_reg_list = NULL;
310  if (rtos == NULL)
311  return -1;
312 
313  if (thread_id == 0)
314  return -2;
315 
316  if (rtos->rtos_specific_params == NULL)
317  return -1;
318 
319  param = (const struct embKernel_params *) rtos->rtos_specific_params;
320 
321  /* Read the stack pointer */
322  retval = target_read_buffer(rtos->target, thread_id + param->thread_stack_offset, param->pointer_width,
323  (uint8_t *) &stack_ptr);
324  if (retval != ERROR_OK) {
325  LOG_ERROR("Error reading stack frame from embKernel thread");
326  return retval;
327  }
328 
329  return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list);
330 }
331 
333 {
334  unsigned int i;
335  *symbol_list = calloc(ARRAY_SIZE(embKernel_symbol_list), sizeof(symbol_table_elem_t));
336 
337  for (i = 0; i < ARRAY_SIZE(embKernel_symbol_list); i++)
338  (*symbol_list)[i].symbol_name = embKernel_symbol_list[i];
339 
340  return 0;
341 }
342 
const unsigned char thread_stack_offset
Definition: embKernel.c:73
const unsigned char pointer_width
Definition: embKernel.c:70
char * thread_name_str
Definition: rtos.h:42
bool exists
Definition: rtos.h:41
threadid_t threadid
Definition: rtos.h:40
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
const unsigned char thread_priority_offset
Definition: embKernel.c:75
Definition: rtos.h:46
int thread_count
Definition: rtos.h:55
const char * name
Name of this type of target.
Definition: target_type.h:42
struct target * target
Definition: rtos.h:50
const struct rtos_register_stacking rtos_embkernel_Cortex_M_stacking
static int embKernel_create(struct target *target)
Definition: embKernel.c:119
#define ERROR_FAIL
Definition: log.h:150
symbol_address_t address
Definition: rtos.h:35
static const char *const embKernel_symbol_list[]
Definition: embKernel.c:59
const char * name
Definition: rtos.h:61
Definition: rtos.h:60
void rtos_free_threadlist(struct rtos *rtos)
Definition: rtos.c:550
const unsigned char thread_name_offset
Definition: embKernel.c:74
static bool embKernel_detect_rtos(struct target *target)
Definition: embKernel.c:110
static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
Definition: embKernel.c:332
Table should be terminated by an element with NULL in symbol_name.
Definition: rtos.h:33
const struct rtos_register_stacking * stacking_info
Definition: embKernel.c:79
threadid_t current_thread
Definition: rtos.h:53
static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
Definition: embKernel.c:303
const unsigned char rtos_list_size
Definition: embKernel.c:72
#define LOG_ERROR(expr...)
Definition: log.h:129
const unsigned char iterable_task_owner_offset
Definition: embKernel.c:78
static const char * target_name(struct target *target)
Returns the instance-specific name of the specified target.
Definition: target.h:223
symbol_table_elem_t * symbols
Definition: rtos.h:49
static int embKernel_update_threads(struct rtos *rtos)
Definition: embKernel.c:183
int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, int64_t stack_ptr, char **hex_reg_list)
Definition: rtos.c:456
#define LOG_OUTPUT(expr...)
Definition: log.h:138
static const struct embKernel_params embKernel_params_list[]
Definition: embKernel.c:82
struct target_type * type
Definition: target.h:127
void * rtos_specific_params
Definition: rtos.h:57
const char * target_name
Definition: embKernel.c:69
char * extra_info_str
Definition: rtos.h:43
static int embKernel_get_tasks_details(struct rtos *rtos, int64_t iterable, const struct embKernel_params *param, struct thread_detail *details, const char *state_str)
Definition: embKernel.c:136
int64_t threadid_t
Definition: rtos.h:25
static struct aice_port_param_s param
#define ARRAY_SIZE(x)
Compute the number of elements of a variable length array.
Definition: types.h:69
#define ERROR_OK
Definition: log.h:144
const unsigned char thread_priority_width
Definition: embKernel.c:76
const unsigned char thread_count_width
Definition: embKernel.c:71
The JTAG interface can be implemented with a software or hardware fifo.
struct rtos_type embKernel_rtos
Definition: embKernel.c:40
struct thread_detail * thread_details
Definition: rtos.h:54
#define NULL
Definition: usb.h:27
#define LOG_WARNING(expr...)
Definition: log.h:126
struct rtos * rtos
Definition: target.h:193
const unsigned char iterable_next_offset
Definition: embKernel.c:77
Definition: target.h:126
#define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE
Definition: embKernel.c:32