OpenOCD
mqx.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2014 by Marian Cingel *
5  * cingel.marian@gmail.com *
6  ***************************************************************************/
7 
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11 
12 #include <stdint.h>
13 #include <helper/time_support.h>
14 #include <jtag/jtag.h>
15 #include "target/target.h"
16 #include "rtos.h"
17 #include "helper/log.h"
18 #include "helper/types.h"
19 #include "rtos_mqx_stackings.h"
20 
21 /* constants */
22 #define MQX_THREAD_NAME_LENGTH (255)
23 #define MQX_KERNEL_OFFSET_TDLIST (0x0108)
24 #define MQX_KERNEL_OFFSET_SYSTEM_TASK (0x0050)
25 #define MQX_KERNEL_OFFSET_ACTIVE_TASK (0x001C)
26 #define MQX_KERNEL_OFFSET_CAPABILITY (0x0000)
27 #define MQX_QUEUE_OFFSET_SIZE (0x0008)
28 #define MQX_TASK_OFFSET_STATE (0x0008)
29 #define MQX_TASK_OFFSET_ID (0x000c)
30 #define MQX_TASK_OFFSET_TEMPLATE (0x0068)
31 #define MQX_TASK_OFFSET_STACK (0x0014)
32 #define MQX_TASK_OFFSET_TDLIST (0x006C)
33 #define MQX_TASK_OFFSET_NEXT (0x0000)
34 #define MQX_TASK_TEMPLATE_OFFSET_NAME (0x0010)
35 #define MQX_TASK_OFFSET_ERROR_CODE (0x005C)
36 #define MQX_TASK_STATE_MASK (0xFFF)
37 
38 /* types */
42 };
43 
44 enum mqx_arch {
46 };
47 
48 struct mqx_params {
49  const char *target_name;
50  const enum mqx_arch target_arch;
52 };
53 
54 struct mqx_state {
55  uint32_t state;
56  char *name;
57 };
58 
59 /* local data */
60 static const struct mqx_state mqx_states[] = {
61  { 0x0002, "READY" },
62  { 0x0003, "BLOCKED" },
63  { 0x0005, "RCV_SPECIFIC_BLOCKED" },
64  { 0x0007, "RCV_ANY_BLOCKED" },
65  { 0x0009, "DYING" },
66  { 0x000B, "UNHANDLED_INT_BLOCKED" },
67  { 0x000D, "SEND_BLOCKED" },
68  { 0x000F, "BREAKPOINT_BLOCKED" },
69  { 0x0211, "IO_BLOCKED" },
70  { 0x0021, "SEM_BLOCKED" },
71  { 0x0223, "MUTEX_BLOCKED" },
72  { 0x0025, "EVENT_BLOCKED" },
73  { 0x0229, "TASK_QUEUE_BLOCKED" },
74  { 0x042B, "LWSEM_BLOCKED" },
75  { 0x042D, "LWEVENT_BLOCKED" },
76 };
77 
78 static const char * const mqx_symbol_list[] = {
79  "_mqx_kernel_data",
80  "MQX_init_struct",
81  NULL
82 };
83 
84 static const struct mqx_params mqx_params_list[] = {
86 };
87 
88 /*
89  * Perform simple address check to avoid bus fault.
90  */
92  struct rtos *rtos,
93  uint32_t address
94 )
95 {
96  enum mqx_arch arch_type = ((struct mqx_params *)rtos->rtos_specific_params)->target_arch;
97  const char *targetname = ((struct mqx_params *)rtos->rtos_specific_params)->target_name;
98 
99  /* Cortex-M address range */
100  if (arch_type == mqx_arch_cortexm) {
101  if (
102  /* code and sram area */
103  (address && address <= 0x3FFFFFFFu) ||
104  /* external ram area*/
105  (address >= 0x6000000u && address <= 0x9FFFFFFFu)
106  ) {
107  return ERROR_OK;
108  }
109  return ERROR_FAIL;
110  }
111  LOG_ERROR("MQX RTOS - unknown architecture %s", targetname);
112  return ERROR_FAIL;
113 }
114 
115 /*
116  * Wrapper of 'target_read_buffer' fn.
117  * Include address check.
118  */
120  struct target *target,
121  uint32_t address,
122  uint32_t size,
123  uint8_t *buffer
124 )
125 {
126  int status = mqx_valid_address_check(target->rtos, address);
127  if (status != ERROR_OK) {
128  LOG_WARNING("MQX RTOS - target address 0x%" PRIx32 " is not allowed to read", address);
129  return status;
130  }
132  if (status != ERROR_OK) {
133  LOG_ERROR("MQX RTOS - reading target address 0x%" PRIx32" failed", address);
134  return status;
135  }
136  return ERROR_OK;
137 }
138 
139 /*
140  * Get symbol address if present
141  */
142 static int mqx_get_symbol(
143  struct rtos *rtos,
144  enum mqx_symbols symbol,
145  void *result
146 )
147 {
148  /* TODO: additional check ?? */
149  (*(int *)result) = (uint32_t)rtos->symbols[symbol].address;
150  return ERROR_OK;
151 }
152 
153 /*
154  * Get value of struct member by passing
155  * member offset, width and name (debug purpose)
156  */
157 static int mqx_get_member(
158  struct rtos *rtos,
159  const uint32_t base_address,
160  int32_t member_offset,
161  int32_t member_width,
162  const char *member_name,
163  void *result
164 )
165 {
166  int status = ERROR_FAIL;
168  rtos->target, base_address + member_offset, member_width, result
169  );
170  if (status != ERROR_OK)
171  LOG_WARNING("MQX RTOS - cannot read \"%s\" at address 0x%" PRIx32,
172  member_name, (uint32_t)(base_address + member_offset));
173  return status;
174 }
175 
176 /*
177  * Check whether scheduler started
178  */
180  struct rtos *rtos
181 )
182 {
183  uint32_t kernel_data_symbol = 0;
184  uint32_t kernel_data_addr = 0;
185  uint32_t system_td_addr = 0;
186  uint32_t active_td_addr = 0;
187  uint32_t capability_value = 0;
188 
189  /* get '_mqx_kernel_data' symbol */
190  if (mqx_get_symbol(rtos, MQX_VAL_MQX_KERNEL_DATA, &kernel_data_symbol) != ERROR_OK)
191  return ERROR_FAIL;
192 
193  /* get '_mqx_kernel_data' */
194  if (mqx_get_member(rtos, kernel_data_symbol, 0, 4,
195  "_mqx_kernel_data", &kernel_data_addr) != ERROR_OK)
196  return ERROR_FAIL;
197 
198  /* return if '_mqx_kernel_data' is NULL or default 0xFFFFFFFF */
199  if (kernel_data_addr == 0 || kernel_data_addr == (uint32_t)(-1))
200  return ERROR_FAIL;
201  /* get kernel_data->ADDRESSING_CAPABILITY */
202  if (mqx_get_member(rtos, kernel_data_addr, MQX_KERNEL_OFFSET_CAPABILITY, 4,
203  "kernel_data->ADDRESSING_CAPABILITY", (void *)&capability_value) != ERROR_OK)
204  return ERROR_FAIL;
205 
206  /* check first member, the '_mqx_kernel_data->ADDRESSING_CAPABILITY'.
207  it suppose to be set to value 8 */
208  if (capability_value != 8) {
209  LOG_WARNING("MQX RTOS - value of '_mqx_kernel_data->ADDRESSING_CAPABILITY' contains invalid value");
210  return ERROR_FAIL;
211  }
212  /* get active ptr */
213  if (mqx_get_member(rtos, kernel_data_addr, MQX_KERNEL_OFFSET_ACTIVE_TASK, 4,
214  "kernel_data->ACTIVE_PTR", (void *)&active_td_addr) != ERROR_OK)
215  return ERROR_FAIL;
216 
217  /* active task is system task, scheduler has not not run yet */
218  system_td_addr = kernel_data_addr + MQX_KERNEL_OFFSET_SYSTEM_TASK;
219  if (active_td_addr == system_td_addr) {
220  LOG_WARNING("MQX RTOS - scheduler does not run");
221  return ERROR_FAIL;
222  }
223  return ERROR_OK;
224 }
225 
226 /*
227  * API function, return true if MQX is present
228  */
229 static bool mqx_detect_rtos(
230  struct target *target
231 )
232 {
233  if (
234  (target->rtos->symbols) &&
236  ) {
237  return true;
238  }
239  return false;
240 }
241 
242 /*
243  * API function, pass MQX extra info to context data
244  */
245 static int mqx_create(
246  struct target *target
247 )
248 {
249  /* check target name against supported architectures */
250  for (unsigned int i = 0; i < ARRAY_SIZE(mqx_params_list); i++) {
251  if (strcmp(mqx_params_list[i].target_name, target_type_name(target)) == 0) {
253  /* LOG_DEBUG("MQX RTOS - valid architecture: %s", target_type_name(target)); */
254  return 0;
255  }
256  }
257  LOG_ERROR("MQX RTOS - could not find target \"%s\" in MQX compatibility list", target_type_name(target));
258  return -1;
259 }
260 
261 /*
262  * API function, update list of threads
263  */
265  struct rtos *rtos
266 )
267 {
268  uint32_t task_queue_addr = 0;
269  uint32_t kernel_data_addr = 0;
270  uint16_t task_queue_size = 0;
271  uint32_t active_td_addr = 0;
272 
274  return -3;
275 
276  if (!rtos->symbols)
277  return -4;
278 
279  /* clear old data */
281  /* check scheduler */
283  return ERROR_FAIL;
284  /* get kernel_data symbol */
285  if (mqx_get_symbol(rtos, MQX_VAL_MQX_KERNEL_DATA, &kernel_data_addr) != ERROR_OK)
286  return ERROR_FAIL;
287 
288  /* read kernel_data */
289  if (mqx_get_member(rtos, kernel_data_addr, 0, 4,
290  "_mqx_kernel_data", &kernel_data_addr) != ERROR_OK)
291  return ERROR_FAIL;
292 
293  /* get task queue address */
294  task_queue_addr = kernel_data_addr + MQX_KERNEL_OFFSET_TDLIST;
295  /* get task queue size */
296  if (mqx_get_member(rtos, task_queue_addr, MQX_QUEUE_OFFSET_SIZE, 2,
297  "kernel_data->TD_LIST.SIZE", &task_queue_size) != ERROR_OK)
298  return ERROR_FAIL;
299 
300  /* get active ptr */
301  if (mqx_get_member(rtos, kernel_data_addr, MQX_KERNEL_OFFSET_ACTIVE_TASK, 4,
302  "kernel_data->ACTIVE_PTR", (void *)&active_td_addr) != ERROR_OK)
303  return ERROR_FAIL;
304 
305  /* setup threads info */
306  rtos->thread_count = task_queue_size;
307  rtos->current_thread = 0;
308  rtos->thread_details = calloc(rtos->thread_count, sizeof(struct thread_detail));
309  if (!rtos->thread_details)
310  return ERROR_FAIL;
311 
312  /* loop over each task and setup thread details,
313  the current_taskpool_addr is set to queue head
314  NOTE: debugging functions task create/destroy
315  might cause to show invalid data.
316  */
317  for (
318  uint32_t i = 0, taskpool_addr = task_queue_addr;
319  i < (uint32_t)rtos->thread_count;
320  i++
321  ) {
322  uint8_t task_name[MQX_THREAD_NAME_LENGTH + 1];
323  uint32_t task_addr = 0, task_template = 0, task_state = 0;
324  uint32_t task_name_addr = 0, task_id = 0, task_errno = 0;
325  uint32_t state_index = 0;
326  uint32_t extra_info_length = 0;
327  char *state_name = "Unknown";
328 
329  /* set current taskpool address */
330  if (mqx_get_member(rtos, taskpool_addr, MQX_TASK_OFFSET_NEXT, 4,
331  "td_struct_ptr->NEXT", &taskpool_addr) != ERROR_OK)
332  return ERROR_FAIL;
333 
334  /* get task address from taskpool */
335  task_addr = taskpool_addr - MQX_TASK_OFFSET_TDLIST;
336  /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR' */
337  if (mqx_get_member(rtos, task_addr, MQX_TASK_OFFSET_TEMPLATE, 4,
338  "td_struct_ptr->TEMPLATE_LIST_PTR", &task_template) != ERROR_OK)
339  return ERROR_FAIL;
340 
341  /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR->NAME' */
342  if (mqx_get_member(rtos, task_template, MQX_TASK_TEMPLATE_OFFSET_NAME, 4,
343  "td_struct_ptr->TEMPLATE_LIST_PTR->NAME", &task_name_addr) != ERROR_OK)
344  return ERROR_FAIL;
345 
346  /* get value of 'td_struct->TEMPLATE_LIST_PTR->NAME' */
347  if (mqx_get_member(rtos, task_name_addr, 0, MQX_THREAD_NAME_LENGTH,
348  "*td_struct_ptr->TEMPLATE_LIST_PTR->NAME", task_name) != ERROR_OK)
349  return ERROR_FAIL;
350 
351  /* always terminate last character by force,
352  otherwise openocd might fail if task_name
353  has corrupted data */
354  task_name[MQX_THREAD_NAME_LENGTH] = '\0';
355  /* get value of 'td_struct_ptr->TASK_ID' */
356  if (mqx_get_member(rtos, task_addr, MQX_TASK_OFFSET_ID, 4,
357  "td_struct_ptr->TASK_ID", &task_id) != ERROR_OK)
358  return ERROR_FAIL;
359 
360  /* get task errno */
362  "td_struct_ptr->TASK_ERROR_CODE", &task_errno) != ERROR_OK)
363  return ERROR_FAIL;
364 
365  /* get value of 'td_struct_ptr->STATE' */
366  if (mqx_get_member(rtos, task_addr, MQX_TASK_OFFSET_STATE, 4,
367  "td_struct_ptr->STATE", &task_state) != ERROR_OK)
368  return ERROR_FAIL;
369 
370  task_state &= MQX_TASK_STATE_MASK;
371  /* and search for defined state */
372  for (state_index = 0; state_index < ARRAY_SIZE(mqx_states); state_index++) {
373  if (mqx_states[state_index].state == task_state) {
374  state_name = mqx_states[state_index].name;
375  break;
376  }
377  }
378 
379  /* setup thread details struct */
380  rtos->thread_details[i].threadid = task_id;
381  rtos->thread_details[i].exists = true;
382  /* set thread name */
383  rtos->thread_details[i].thread_name_str = malloc(strlen((void *)task_name) + 1);
385  return ERROR_FAIL;
386  strcpy(rtos->thread_details[i].thread_name_str, (void *)task_name);
387  /* set thread extra info
388  * - task state
389  * - task address
390  * - task errno
391  * calculate length as:
392  * state length + address length + errno length + formatter length
393  */
394  extra_info_length += strlen((void *)state_name) + 7 + 13 + 8 + 15 + 8;
395  rtos->thread_details[i].extra_info_str = malloc(extra_info_length + 1);
397  return ERROR_FAIL;
398  snprintf(rtos->thread_details[i].extra_info_str, extra_info_length,
399  "State: %s, Address: 0x%" PRIx32 ", Error Code: %" PRIu32,
400  state_name, task_addr, task_errno
401  );
402  /* set active thread */
403  if (active_td_addr == task_addr)
404  rtos->current_thread = task_id;
405  }
406  return ERROR_OK;
407 }
408 
409 /*
410  * API function, get info of selected thread
411  */
413  struct rtos *rtos,
414  int64_t thread_id,
415  struct rtos_reg **reg_list,
416  int *num_regs
417 )
418 {
419  int64_t stack_ptr = 0;
420  uint32_t my_task_addr = 0;
421  uint32_t task_queue_addr = 0;
422  uint32_t task_queue_size = 0;
423  uint32_t kernel_data_addr = 0;
424 
425  if (thread_id == 0) {
426  LOG_ERROR("MQX RTOS - invalid threadid: 0x%X", (int)thread_id);
427  return ERROR_FAIL;
428  }
430  return ERROR_FAIL;
431  /* get kernel_data symbol */
432  if (mqx_get_symbol(rtos, MQX_VAL_MQX_KERNEL_DATA, &kernel_data_addr) != ERROR_OK)
433  return ERROR_FAIL;
434 
435  /* read kernel_data */
436  if (mqx_get_member(rtos, kernel_data_addr, 0, 4,
437  "_mqx_kernel_data", &kernel_data_addr) != ERROR_OK)
438  return ERROR_FAIL;
439 
440  /* get task queue address */
441  task_queue_addr = kernel_data_addr + MQX_KERNEL_OFFSET_TDLIST;
442  /* get task queue size */
443  if (mqx_get_member(rtos, task_queue_addr, MQX_QUEUE_OFFSET_SIZE, 2,
444  "kernel_data->TD_LIST.SIZE", &task_queue_size) != ERROR_OK)
445  return ERROR_FAIL;
446 
447  /* search for taskid */
448  for (
449  uint32_t i = 0, taskpool_addr = task_queue_addr;
450  i < (uint32_t)rtos->thread_count;
451  i++
452  ) {
453  uint32_t tmp_address = 0, task_addr = 0;
454  uint32_t task_id = 0;
455  /* set current taskpool address */
456  tmp_address = taskpool_addr;
457  if (mqx_get_member(rtos, tmp_address, MQX_TASK_OFFSET_NEXT, 4,
458  "td_struct_ptr->NEXT", &taskpool_addr) != ERROR_OK)
459  return ERROR_FAIL;
460 
461  /* get task address from taskpool */
462  task_addr = taskpool_addr - MQX_TASK_OFFSET_TDLIST;
463  /* get value of td_struct->TASK_ID */
464  if (mqx_get_member(rtos, task_addr, MQX_TASK_OFFSET_ID, 4,
465  "td_struct_ptr->TASK_ID", &task_id) != ERROR_OK)
466  return ERROR_FAIL;
467 
468  /* found taskid, break */
469  if (task_id == thread_id) {
470  my_task_addr = task_addr;
471  break;
472  }
473  }
474  if (!my_task_addr) {
475  LOG_ERROR("MQX_RTOS - threadid %" PRId64 " does not match any task", thread_id);
476  return ERROR_FAIL;
477  }
478  /* get task stack head address */
479  if (mqx_get_member(rtos, my_task_addr, MQX_TASK_OFFSET_STACK, 4,
480  "task->STACK_PTR", &stack_ptr) != ERROR_OK)
481  return ERROR_FAIL;
482 
484  rtos->target, ((struct mqx_params *)rtos->rtos_specific_params)->stacking_info, stack_ptr, reg_list, num_regs
485  );
486 }
487 
488 /* API function, export list of required symbols */
489 static int mqx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
490 {
491  *symbol_list = calloc(ARRAY_SIZE(mqx_symbol_list), sizeof(struct symbol_table_elem));
492  if (!*symbol_list)
493  return ERROR_FAIL;
494  /* export required symbols */
495  for (int i = 0; i < (int)(ARRAY_SIZE(mqx_symbol_list)); i++)
496  (*symbol_list)[i].symbol_name = mqx_symbol_list[i];
497  return ERROR_OK;
498 }
499 
500 const struct rtos_type mqx_rtos = {
501  .name = "mqx",
502  .detect_rtos = mqx_detect_rtos,
503  .create = mqx_create,
504  .update_threads = mqx_update_threads,
505  .get_thread_reg_list = mqx_get_thread_reg_list,
506  .get_symbol_list_to_lookup = mqx_get_symbol_list_to_lookup,
507 };
The JTAG interface can be implemented with a software or hardware fifo.
#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 int mqx_target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer)
Definition: mqx.c:119
#define MQX_KERNEL_OFFSET_SYSTEM_TASK
Definition: mqx.c:24
#define MQX_TASK_OFFSET_STATE
Definition: mqx.c:28
static int mqx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs)
Definition: mqx.c:412
#define MQX_TASK_OFFSET_ERROR_CODE
Definition: mqx.c:35
#define MQX_KERNEL_OFFSET_CAPABILITY
Definition: mqx.c:26
#define MQX_TASK_OFFSET_NEXT
Definition: mqx.c:33
#define MQX_THREAD_NAME_LENGTH
Definition: mqx.c:22
static int mqx_is_scheduler_running(struct rtos *rtos)
Definition: mqx.c:179
static int mqx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
Definition: mqx.c:489
static int mqx_get_symbol(struct rtos *rtos, enum mqx_symbols symbol, void *result)
Definition: mqx.c:142
#define MQX_TASK_TEMPLATE_OFFSET_NAME
Definition: mqx.c:34
static const struct mqx_params mqx_params_list[]
Definition: mqx.c:84
#define MQX_TASK_OFFSET_ID
Definition: mqx.c:29
mqx_symbols
Definition: mqx.c:39
@ MQX_VAL_MQX_INIT_STRUCT
Definition: mqx.c:41
@ MQX_VAL_MQX_KERNEL_DATA
Definition: mqx.c:40
static int mqx_get_member(struct rtos *rtos, const uint32_t base_address, int32_t member_offset, int32_t member_width, const char *member_name, void *result)
Definition: mqx.c:157
#define MQX_TASK_OFFSET_TEMPLATE
Definition: mqx.c:30
#define MQX_TASK_STATE_MASK
Definition: mqx.c:36
static int mqx_valid_address_check(struct rtos *rtos, uint32_t address)
Definition: mqx.c:91
static const struct mqx_state mqx_states[]
Definition: mqx.c:60
static int mqx_update_threads(struct rtos *rtos)
Definition: mqx.c:264
static int mqx_create(struct target *target)
Definition: mqx.c:245
#define MQX_KERNEL_OFFSET_TDLIST
Definition: mqx.c:23
static const char *const mqx_symbol_list[]
Definition: mqx.c:78
#define MQX_TASK_OFFSET_STACK
Definition: mqx.c:31
mqx_arch
Definition: mqx.c:44
@ mqx_arch_cortexm
Definition: mqx.c:45
#define MQX_TASK_OFFSET_TDLIST
Definition: mqx.c:32
#define MQX_KERNEL_OFFSET_ACTIVE_TASK
Definition: mqx.c:25
static bool mqx_detect_rtos(struct target *target)
Definition: mqx.c:229
const struct rtos_type mqx_rtos
Definition: mqx.c:500
#define MQX_QUEUE_OFFSET_SIZE
Definition: mqx.c:27
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
const struct rtos_register_stacking rtos_mqx_arm_v7m_stacking
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
Definition: mqx.c:48
const struct rtos_register_stacking * stacking_info
Definition: mqx.c:51
enum mqx_arch target_arch
Definition: mqx.c:50
const char * target_name
Definition: mqx.c:49
Definition: mqx.c:54
char * name
Definition: mqx.c:56
uint32_t state
Definition: mqx.c:55
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
Definition: target.h:116
struct rtos * rtos
Definition: target.h:183
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:2407
const char * target_type_name(const struct target *target)
Get the target type name.
Definition: target.c:736
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
#define NULL
Definition: usb.h:16
uint8_t status[4]
Definition: vdebug.c:17
uint8_t state[4]
Definition: vdebug.c:21