OpenOCD
uCOS-III.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2017 by Square, Inc. *
5  * Steven Stallion <stallion@squareup.com> *
6  ***************************************************************************/
7 
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11 
12 #include <helper/log.h>
13 #include <helper/time_support.h>
14 #include <helper/types.h>
15 #include <rtos/rtos.h>
16 #include <target/target.h>
17 #include <target/target_type.h>
18 
20 
21 #ifndef UCOS_III_MAX_STRLEN
22 #define UCOS_III_MAX_STRLEN 64
23 #endif
24 
25 #ifndef UCOS_III_MAX_THREADS
26 #define UCOS_III_MAX_THREADS 256
27 #endif
28 
30  const char *target_name;
31  const unsigned char pointer_width;
34 };
35 
37  const struct ucos_iii_params *params;
45  size_t num_threads;
47 };
48 
49 static const struct ucos_iii_params ucos_iii_params_list[] = {
50  {
51  .target_name = "cortex_m",
52  .pointer_width = sizeof(uint32_t),
53  .threadid_start = 1,
55  },
56  {
57  .target_name = "esirisc",
58  .pointer_width = sizeof(uint32_t),
59  .threadid_start = 1,
61  },
62 };
63 
64 static const char * const ucos_iii_symbol_list[] = {
65  "OSRunning",
66  "OSTCBCurPtr",
67  "OSTaskDbgListPtr",
68  "OSTaskQty",
69 
70  /* also see: contrib/rtos-helpers/uCOS-III-openocd.c */
71  "openocd_OS_TCB_StkPtr_offset",
72  "openocd_OS_TCB_NamePtr_offset",
73  "openocd_OS_TCB_TaskState_offset",
74  "openocd_OS_TCB_Prio_offset",
75  "openocd_OS_TCB_DbgPrevPtr_offset",
76  "openocd_OS_TCB_DbgNextPtr_offset",
77  NULL
78 };
79 
85 
86  /* also see: contrib/rtos-helpers/uCOS-III-openocd.c */
93 };
94 
95 static const char * const ucos_iii_thread_state_list[] = {
96  "Ready",
97  "Delay",
98  "Pend",
99  "Pend Timeout",
100  "Suspended",
101  "Delay Suspended",
102  "Pend Suspended",
103  "Pend Timeout Suspended",
104 };
105 
106 static int ucos_iii_find_or_create_thread(struct rtos *rtos, symbol_address_t thread_address,
107  threadid_t *threadid)
108 {
110  size_t thread_index;
111 
112  for (thread_index = 0; thread_index < params->num_threads; thread_index++)
113  if (params->threads[thread_index] == thread_address)
114  goto found;
115 
116  if (params->num_threads == UCOS_III_MAX_THREADS) {
117  LOG_WARNING("uCOS-III: too many threads; increase UCOS_III_MAX_THREADS");
118  return ERROR_FAIL;
119  }
120 
121  params->threads[thread_index] = thread_address;
122  params->num_threads++;
123 found:
124  *threadid = thread_index + params->params->threadid_start;
125  return ERROR_OK;
126 }
127 
128 static int ucos_iii_find_thread_address(struct rtos *rtos, threadid_t threadid,
129  symbol_address_t *thread_address)
130 {
132  size_t thread_index;
133 
134  thread_index = threadid - params->params->threadid_start;
135  if (thread_index >= params->num_threads) {
136  LOG_ERROR("uCOS-III: failed to find thread address");
137  return ERROR_FAIL;
138  }
139 
140  *thread_address = params->threads[thread_index];
141  return ERROR_OK;
142 }
143 
144 static int ucos_iii_find_last_thread_address(struct rtos *rtos, symbol_address_t *thread_address)
145 {
147  int retval;
148 
149  /* read the thread list head */
150  symbol_address_t thread_list_address = 0;
151 
152  retval = target_read_memory(rtos->target,
154  params->params->pointer_width,
155  1,
156  (void *)&thread_list_address);
157  if (retval != ERROR_OK) {
158  LOG_ERROR("uCOS-III: failed to read thread list address");
159  return retval;
160  }
161 
162  /* advance to end of thread list */
163  do {
164  *thread_address = thread_list_address;
165 
166  retval = target_read_memory(rtos->target,
167  thread_list_address + params->thread_next_offset,
168  params->params->pointer_width,
169  1,
170  (void *)&thread_list_address);
171  if (retval != ERROR_OK) {
172  LOG_ERROR("uCOS-III: failed to read next thread address");
173  return retval;
174  }
175  } while (thread_list_address != 0);
176 
177  return ERROR_OK;
178 }
179 
181 {
183 
184  if (params->thread_offsets_updated)
185  return ERROR_OK;
186 
187  const struct thread_offset_map {
188  enum ucos_iii_symbol_values symbol_value;
189  symbol_address_t *thread_offset;
190  } thread_offset_maps[] = {
191  {
193  &params->thread_stack_offset,
194  },
195  {
197  &params->thread_name_offset,
198  },
199  {
201  &params->thread_state_offset,
202  },
203  {
205  &params->thread_priority_offset,
206  },
207  {
209  &params->thread_prev_offset,
210  },
211  {
213  &params->thread_next_offset,
214  },
215  };
216 
217  for (size_t i = 0; i < ARRAY_SIZE(thread_offset_maps); i++) {
218  const struct thread_offset_map *thread_offset_map = &thread_offset_maps[i];
219 
220  int retval = target_read_memory(rtos->target,
221  rtos->symbols[thread_offset_map->symbol_value].address,
222  params->params->pointer_width,
223  1,
224  (void *)thread_offset_map->thread_offset);
225  if (retval != ERROR_OK) {
226  LOG_ERROR("uCOS-III: failed to read thread offset");
227  return retval;
228  }
229  }
230 
231  params->thread_offsets_updated = true;
232  return ERROR_OK;
233 }
234 
235 static bool ucos_iii_detect_rtos(struct target *target)
236 {
237  return target->rtos->symbols &&
239 }
240 
241 static int ucos_iii_reset_handler(struct target *target, enum target_reset_mode reset_mode, void *priv)
242 {
244 
245  params->thread_offsets_updated = false;
246  params->num_threads = 0;
247 
248  return ERROR_OK;
249 }
250 
251 static int ucos_iii_create(struct target *target)
252 {
253  struct ucos_iii_private *params;
254 
255  for (size_t i = 0; i < ARRAY_SIZE(ucos_iii_params_list); i++)
256  if (strcmp(ucos_iii_params_list[i].target_name, target->type->name) == 0) {
257  params = calloc(1, sizeof(*params));
258  if (!params) {
259  LOG_ERROR("uCOS-III: out of memory");
260  return ERROR_FAIL;
261  }
262 
263  params->params = &ucos_iii_params_list[i];
265 
267 
268  return ERROR_OK;
269  }
270 
271  LOG_ERROR("uCOS-III: target not supported: %s", target->type->name);
272  return ERROR_FAIL;
273 }
274 
275 static int ucos_iii_update_threads(struct rtos *rtos)
276 {
278  int retval;
279 
280  if (!rtos->symbols) {
281  LOG_ERROR("uCOS-III: symbol list not loaded");
282  return ERROR_FAIL;
283  }
284 
285  /* free previous thread details */
287 
288  /* verify RTOS is running */
289  uint8_t rtos_running;
290 
291  retval = target_read_u8(rtos->target,
293  &rtos_running);
294  if (retval != ERROR_OK) {
295  LOG_ERROR("uCOS-III: failed to read RTOS running");
296  return retval;
297  }
298 
299  if (rtos_running != 1 && rtos_running != 0) {
300  LOG_ERROR("uCOS-III: invalid RTOS running value");
301  return ERROR_FAIL;
302  }
303 
304  if (!rtos_running) {
305  rtos->thread_details = calloc(1, sizeof(struct thread_detail));
306  if (!rtos->thread_details) {
307  LOG_ERROR("uCOS-III: out of memory");
308  return ERROR_FAIL;
309  }
310 
311  rtos->thread_count = 1;
313  rtos->thread_details->exists = true;
314  rtos->current_thread = 0;
315 
316  return ERROR_OK;
317  }
318 
319  /* update thread offsets */
321  if (retval != ERROR_OK) {
322  LOG_ERROR("uCOS-III: failed to update thread offsets");
323  return retval;
324  }
325 
326  /* read current thread address */
327  symbol_address_t current_thread_address = 0;
328 
329  retval = target_read_memory(rtos->target,
331  params->params->pointer_width,
332  1,
333  (void *)&current_thread_address);
334  if (retval != ERROR_OK) {
335  LOG_ERROR("uCOS-III: failed to read current thread address");
336  return retval;
337  }
338 
339  /* read number of tasks */
340  retval = target_read_u16(rtos->target,
342  (void *)&rtos->thread_count);
343  if (retval != ERROR_OK) {
344  LOG_ERROR("uCOS-III: failed to read thread count");
345  return retval;
346  }
347 
348  rtos->thread_details = calloc(rtos->thread_count, sizeof(struct thread_detail));
349  if (!rtos->thread_details) {
350  LOG_ERROR("uCOS-III: out of memory");
351  return ERROR_FAIL;
352  }
353 
354  /*
355  * uC/OS-III adds tasks in LIFO order; advance to the end of the
356  * list and work backwards to preserve the intended order.
357  */
358  symbol_address_t thread_address = 0;
359 
360  retval = ucos_iii_find_last_thread_address(rtos, &thread_address);
361  if (retval != ERROR_OK) {
362  LOG_ERROR("uCOS-III: failed to find last thread address");
363  return retval;
364  }
365 
366  for (int i = 0; i < rtos->thread_count; i++) {
368  char thread_str_buffer[UCOS_III_MAX_STRLEN + 1];
369 
370  /* find or create new threadid */
371  retval = ucos_iii_find_or_create_thread(rtos, thread_address, &thread_detail->threadid);
372  if (retval != ERROR_OK) {
373  LOG_ERROR("uCOS-III: failed to find or create thread");
374  return retval;
375  }
376 
377  if (thread_address == current_thread_address)
379 
380  thread_detail->exists = true;
381 
382  /* read thread name */
383  symbol_address_t thread_name_address = 0;
384 
385  retval = target_read_memory(rtos->target,
386  thread_address + params->thread_name_offset,
387  params->params->pointer_width,
388  1,
389  (void *)&thread_name_address);
390  if (retval != ERROR_OK) {
391  LOG_ERROR("uCOS-III: failed to name address");
392  return retval;
393  }
394 
395  retval = target_read_buffer(rtos->target,
396  thread_name_address,
397  sizeof(thread_str_buffer),
398  (void *)thread_str_buffer);
399  if (retval != ERROR_OK) {
400  LOG_ERROR("uCOS-III: failed to read thread name");
401  return retval;
402  }
403 
404  thread_str_buffer[sizeof(thread_str_buffer) - 1] = '\0';
405  thread_detail->thread_name_str = strdup(thread_str_buffer);
406 
407  /* read thread extra info */
408  uint8_t thread_state;
409  uint8_t thread_priority;
410 
411  retval = target_read_u8(rtos->target,
412  thread_address + params->thread_state_offset,
413  &thread_state);
414  if (retval != ERROR_OK) {
415  LOG_ERROR("uCOS-III: failed to read thread state");
416  return retval;
417  }
418 
419  retval = target_read_u8(rtos->target,
420  thread_address + params->thread_priority_offset,
421  &thread_priority);
422  if (retval != ERROR_OK) {
423  LOG_ERROR("uCOS-III: failed to read thread priority");
424  return retval;
425  }
426 
427  const char *thread_state_str;
428 
429  if (thread_state < ARRAY_SIZE(ucos_iii_thread_state_list))
430  thread_state_str = ucos_iii_thread_state_list[thread_state];
431  else
432  thread_state_str = "Unknown";
433 
434  snprintf(thread_str_buffer, sizeof(thread_str_buffer), "State: %s, Priority: %d",
435  thread_state_str, thread_priority);
436  thread_detail->extra_info_str = strdup(thread_str_buffer);
437 
438  /* read previous thread address */
439  retval = target_read_memory(rtos->target,
440  thread_address + params->thread_prev_offset,
441  params->params->pointer_width,
442  1,
443  (void *)&thread_address);
444  if (retval != ERROR_OK) {
445  LOG_ERROR("uCOS-III: failed to read previous thread address");
446  return retval;
447  }
448  }
449 
450  return ERROR_OK;
451 }
452 
454  struct rtos_reg **reg_list, int *num_regs)
455 {
457  int retval;
458 
459  /* find thread address for threadid */
460  symbol_address_t thread_address = 0;
461 
462  retval = ucos_iii_find_thread_address(rtos, threadid, &thread_address);
463  if (retval != ERROR_OK) {
464  LOG_ERROR("uCOS-III: failed to find thread address");
465  return retval;
466  }
467 
468  /* read thread stack address */
469  symbol_address_t stack_address = 0;
470 
471  retval = target_read_memory(rtos->target,
472  thread_address + params->thread_stack_offset,
473  params->params->pointer_width,
474  1,
475  (void *)&stack_address);
476  if (retval != ERROR_OK) {
477  LOG_ERROR("uCOS-III: failed to read stack address");
478  return retval;
479  }
480 
482  params->params->stacking_info,
483  stack_address,
484  reg_list,
485  num_regs);
486 }
487 
488 static int ucos_iii_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
489 {
490  *symbol_list = calloc(ARRAY_SIZE(ucos_iii_symbol_list), sizeof(struct symbol_table_elem));
491  if (!*symbol_list) {
492  LOG_ERROR("uCOS-III: out of memory");
493  return ERROR_FAIL;
494  }
495 
496  for (size_t i = 0; i < ARRAY_SIZE(ucos_iii_symbol_list); i++)
497  (*symbol_list)[i].symbol_name = ucos_iii_symbol_list[i];
498 
499  return ERROR_OK;
500 }
501 
502 const struct rtos_type ucos_iii_rtos = {
503  .name = "uCOS-III",
504  .detect_rtos = ucos_iii_detect_rtos,
505  .create = ucos_iii_create,
506  .update_threads = ucos_iii_update_threads,
507  .get_thread_reg_list = ucos_iii_get_thread_reg_list,
508  .get_symbol_list_to_lookup = ucos_iii_get_symbol_list_to_lookup,
509 };
static struct esp_usb_jtag * priv
Definition: esp_usb_jtag.c:219
#define LOG_WARNING(expr ...)
Definition: log.h:129
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define ERROR_OK
Definition: log.h:164
static const struct rtos_register_stacking * stacking_info
Definition: riot.c:73
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:602
void rtos_free_threadlist(struct rtos *rtos)
Definition: rtos.c:695
int64_t symbol_address_t
Definition: rtos.h:16
int64_t threadid_t
Definition: rtos.h:15
const struct rtos_register_stacking rtos_ucos_iii_cortex_m_stacking
const struct rtos_register_stacking rtos_ucos_iii_esi_risc_stacking
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:116
struct rtos * rtos
Definition: target.h:183
struct target_type * type
Definition: target.h:117
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
Definition: linux.c:56
const struct rtos_register_stacking * stacking_info
Definition: uCOS-III.c:33
const unsigned char pointer_width
Definition: uCOS-III.c:31
size_t threadid_start
Definition: uCOS-III.c:32
const char * target_name
Definition: uCOS-III.c:30
symbol_address_t thread_state_offset
Definition: uCOS-III.c:40
symbol_address_t thread_prev_offset
Definition: uCOS-III.c:42
symbol_address_t thread_stack_offset
Definition: uCOS-III.c:38
const struct ucos_iii_params * params
Definition: uCOS-III.c:37
bool thread_offsets_updated
Definition: uCOS-III.c:44
symbol_address_t thread_name_offset
Definition: uCOS-III.c:39
symbol_address_t thread_next_offset
Definition: uCOS-III.c:43
symbol_address_t thread_priority_offset
Definition: uCOS-III.c:41
size_t num_threads
Definition: uCOS-III.c:45
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2407
int target_read_u8(struct target *target, target_addr_t address, uint8_t *value)
Definition: target.c:2598
int target_read_u16(struct target *target, target_addr_t address, uint16_t *value)
Definition: target.c:2574
int target_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
Read count items of size bytes from the memory of target at the address given.
Definition: target.c:1237
int target_register_reset_callback(int(*callback)(struct target *target, enum target_reset_mode reset_mode, void *priv), void *priv)
Definition: target.c:1614
target_reset_mode
Definition: target.h:61
static const char * target_name(const struct target *target)
Returns the instance-specific name of the specified target.
Definition: target.h:233
#define ARRAY_SIZE(x)
Compute the number of elements of a variable length array.
Definition: types.h:57
static int ucos_iii_reset_handler(struct target *target, enum target_reset_mode reset_mode, void *priv)
Definition: uCOS-III.c:241
static int ucos_iii_update_threads(struct rtos *rtos)
Definition: uCOS-III.c:275
ucos_iii_symbol_values
Definition: uCOS-III.c:80
@ UCOS_III_VAL_OS_TCB_CUR_PTR
Definition: uCOS-III.c:82
@ UCOS_III_VAL_OS_TCB_PRIO_OFFSET
Definition: uCOS-III.c:90
@ UCOS_III_VAL_OS_TASK_QTY
Definition: uCOS-III.c:84
@ UCOS_III_VAL_OS_RUNNING
Definition: uCOS-III.c:81
@ UCOS_III_VAL_OS_TCB_NAME_PTR_OFFSET
Definition: uCOS-III.c:88
@ UCOS_III_VAL_OS_TCB_DBG_PREV_PTR_OFFSET
Definition: uCOS-III.c:91
@ UCOS_III_VAL_OS_TCB_TASK_STATE_OFFSET
Definition: uCOS-III.c:89
@ UCOS_III_VAL_OS_TASK_DBG_LIST_PTR
Definition: uCOS-III.c:83
@ UCOS_III_VAL_OS_TCB_STK_PTR_OFFSET
Definition: uCOS-III.c:87
@ UCOS_III_VAL_OS_TCB_DBG_NEXT_PTR_OFFSET
Definition: uCOS-III.c:92
static const char *const ucos_iii_thread_state_list[]
Definition: uCOS-III.c:95
static const struct ucos_iii_params ucos_iii_params_list[]
Definition: uCOS-III.c:49
#define UCOS_III_MAX_STRLEN
Definition: uCOS-III.c:22
static int ucos_iii_create(struct target *target)
Definition: uCOS-III.c:251
static const char *const ucos_iii_symbol_list[]
Definition: uCOS-III.c:64
static int ucos_iii_find_or_create_thread(struct rtos *rtos, symbol_address_t thread_address, threadid_t *threadid)
Definition: uCOS-III.c:106
static int ucos_iii_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
Definition: uCOS-III.c:488
static int ucos_iii_find_thread_address(struct rtos *rtos, threadid_t threadid, symbol_address_t *thread_address)
Definition: uCOS-III.c:128
static int ucos_iii_get_thread_reg_list(struct rtos *rtos, threadid_t threadid, struct rtos_reg **reg_list, int *num_regs)
Definition: uCOS-III.c:453
const struct rtos_type ucos_iii_rtos
Definition: uCOS-III.c:502
#define UCOS_III_MAX_THREADS
Definition: uCOS-III.c:26
static bool ucos_iii_detect_rtos(struct target *target)
Definition: uCOS-III.c:235
static int ucos_iii_update_thread_offsets(struct rtos *rtos)
Definition: uCOS-III.c:180
static int ucos_iii_find_last_thread_address(struct rtos *rtos, symbol_address_t *thread_address)
Definition: uCOS-III.c:144
#define NULL
Definition: usb.h:16